Extension method for Enumerable.Intersperse?

前端 未结 5 1753
被撕碎了的回忆
被撕碎了的回忆 2020-12-11 16:27

I learned the intersperse function from Haskell, and have been looking for an implementation in c#.

Intersperse takes 2 arguments, an IEnumerable source and

相关标签:
5条回答
  • 2020-12-11 17:05

    If you're wondering how to implement it, I would do so like this:

    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> collection, T value)
    {
        foreach(T item in collection)
        {
            yield return item;
            yield return value;
        }
    
        yield break;
    }
    
    0 讨论(0)
  • 2020-12-11 17:14

    Something the others have missed: if you only want it in between items, and not also in front or behind, you need to do an extra check:

    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element)
    {
        bool first = true;
        foreach (T value in source)
        {
            if (!first) yield return element;
            yield return value;
            first = false;
        }
    }
    
    0 讨论(0)
  • 2020-12-11 17:23

    It would be pretty easy to write:

    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T value) {
        bool first = true;
        foreach(T item in source) {
             if(first) { first = false; }
             else { yield return value; }
             yield return item;
        }
    }
    
    0 讨论(0)
  • 2020-12-11 17:23

    Here is an example with more control over inserting the additional item:

    
    public delegate T IntersperseFunc<T>(T prev, T next, int index);
    public delegate T InterspersePrevNextFunc<T>(T prev, T next);
    public delegate T IntersperseIndexFunc<out T>(int index);
    
    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, IntersperseFunc<T> elementFunc)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        using (var enumerator = source.GetEnumerator())
        {
            if (enumerator.MoveNext())
            {
                var index = 0;
                var prev = enumerator.Current;
                yield return prev;
                while (enumerator.MoveNext())
                {
                    var next = enumerator.Current;
                    yield return elementFunc(prev, next, index++);
                    yield return next;
                    prev = next;
                }
            }
        }
    }
    
    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, InterspersePrevNextFunc<T> elementFunc)
        => Intersperse(source, (prev, next, index) => elementFunc(prev, next));
    
    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, IntersperseIndexFunc<T> elementFunc)
        => Intersperse(source, (prev, next, index) => elementFunc(index));
    
    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, Func<T> elementFunc)
        => Intersperse(source, (prev, next, index) => elementFunc());
    
    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element)
        => Intersperse(source, (prev, next, index) => element);
    
    0 讨论(0)
  • 2020-12-11 17:24

    I've coded up a solution that is lazy, in the spirit of Linq solutions! Other solutions I came up with involved traversing the entire list before returning data, and then returning the resulting list.

    Some of the other answers have an if check on every iteration of the loop.

    public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element)
    {
        using (var enumerator = source.GetEnumerator()) {
            if (enumerator.MoveNext()) {
                yield return enumerator.Current;
                while (enumerator.MoveNext()) {
                    yield return element;
                    yield return enumerator.Current;
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题