Showing posts with label extension. Show all posts
Showing posts with label extension. Show all posts

Jul 19, 2019

Intervals 2.0

Updated intervals combining (splicing/clipping) method with the new features of C# 7.0. Intervals passed can overlap.
Two weird classes added for convenience. Pair<T> is handy when you have to switch often between 2 objects. IntBool is a value type which can act as both int and bool.

    public static class CombineIntervals
    {
        public static IEnumerable<(T, T)> Combine<T>(this IEnumerable<(T, T)> inc, IEnumerable<(T, T)> exc = null) where T : IComparable
        {
            if (exc == null) exc = Enumerable.Empty<(T, T)>();
            IEnumerable<(T val, bool br, bool ex) > GetBorders(IEnumerable<(T left, T right)> ranges, bool ex)
            {
                foreach (var (left, right) in ranges)
                {
                    yield return (left, true, ex);
                    yield return (right, false, ex);
                }
            }
            var borders = GetBorders(inc, false).Union(GetBorders(exc, true)).OrderBy(x => x.val).ToArray();
            T start = borders[0].val;
            var state = new Pair<IntBool>();
            foreach (var (val, br, ex) in borders)
            {
                if (state[ex].Xor(br))
                {
                    if (br == state[!ex])
                        yield return (start, val);
                    else start = val;
                }
                state[ex] += br ? 1 : -1;
            }
        }
    }
    public struct Pair<T>
    {
        T a; T b;
        public T this[IntBool i]
        {
            get => i ? b : a;
            set
            {
                if (i) b = value;
                else a = value;
            }
        }
        public override string ToString()
        {
            return $"{a}, {b}";
        }
        internal void Deconstruct(out T x, out T y)
        {
            x = a;
            y = b;
        }
    }
    public struct IntBool
    {
        private int val;
        public static implicit operator IntBool (int x) => new IntBool() { val = x };
        public static implicit operator int(IntBool x) => x.val;
        public static implicit operator IntBool(bool x) => new IntBool() { val = x ? 1 : 0 };
        public static implicit operator bool(IntBool x) => x.val > 0;
        public override string ToString() => val.ToString();
        public bool And(bool x) => val == 1 && x;
        public bool Xor(bool x) => val == 1 && !x || val == 0 && x;
    }

Jan 30, 2016

Circular Linked List

Code:
public static class CircularLinkedList
{
    public static LinkedListNode<T> NextOrFirst<T>(this LinkedListNode<T> current)
    {
        return current.Next ?? current.List.First;
    }

    public static LinkedListNode<T> PreviousOrLast<T>(this LinkedListNode<T> current)
    {
        return current.Previous ?? current.List.Last;
    }

    public static LinkedListNode<T> Rewind<T>(this LinkedListNode<T> current, int num)
    {
        while (num != 0)
        {
            current = num > 0 ? current.NextOrFirst() : current.PreviousOrLast();
            num -= Math.Sign(num);
        }
        return current;
    }
}

Sep 11, 2015

Wrap an object into an IEnumerable of single item

Code:
public static IEnumerable<T> Yield<T>(this T item)
{
    yield return item;
}

Faster TakeBy

Code:
public static IEnumerable<IEnumerable<T>> TakeBy<T>(this IEnumerable<T> source, int count)
{
    var grps = source.Select((val, i) => new { idx = i / count, val }).GroupBy(e => e.idx);
    return grps.Select(g => g.Select(e => e.val));
}

Sep 10, 2015

Combinatorics: get all combinations of k elements from an input sequence


Code:
public static IEnumerable<IEnumerable<T>> Combine<T>(this IEnumerable<T> list, int k = 2, bool repetition = false)
{
    for (int i = 0; i < list.Count(); i++)
    {
        T cur = list.Skip(i).First();
        if (k == 1)
        {
            yield return cur.Yield();
        }
        else
        {
            foreach (var res in list.Skip(i + (repetition ? 0 : 1)).Combine(k - 1, repetition))
            {
                yield return res.Prepend(cur);
            }
        }
    }
}

e.g.
{ 1, 2, 3 }.Combine(2) = {{ 1, 2 }, { 1, 3 }, { 2, 3 }}
{ 1, 2 }.Combine(2, true) = {{ 1, 1 }, { 1, 2 }, { 2, 2 }}
{ 1, 2, 3, 4 }.Combine(3) = {{ 1, 2, 3 }, { 1, 2, 4 }, { 2, 3, 4 }}

May 19, 2015

Linq TakeBy

I was about to write such an extension
But then desided to google for it first, and voila:

Code:
/// <summary>
/// <paramref name="source"/>中の要素を<paramref name="count"/>
/// 個ごとにまとめ直します。
/// 最後の要素数が足りない場合は足りないまま返します。
/// </summary>
public static IEnumerable<IEnumerable<TSource>> TakeBy<TSource>(this IEnumerable<TSource> source, int count)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    if (count < 1)
    {
        throw new ArgumentOutOfRangeException("count");
    }
    while (source.Any())
    {
        yield return source.Take(count);
        source = source.Skip(count);
    }
}

got it here
Isn't it nice?

ps: this variant is much faster