Enumerable.Intersperse的扩展方法?

问题描述 投票:9回答:5

[我从Haskell那里学习了intersperse function,并且一直在用c#寻找实现。

Intersperse采用2个参数,一个IEnumerable 源和一个T元素。它返回一个IEnumerable,元素插入在源的每个元素之间。

一个可能的用例是在整数列表之间放置一个任意整数,例如:

// returns: {1, 0, 2, 0, 3}
(List<int>() {1, 2, 3}).Intersperse(0);

这是string.Join(...)的一般情况。

c# ienumerable
5个回答
13
投票

其他人错过了的东西:如果只希望在项目之间,而不是在前面或后面,则需要进行额外的检查:

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;
    }
}

5
投票

本着Linq解决方案的精神,我编写了一个懒惰的解决方案!我想到的其他解决方案包括在返回数据之前遍历整个列表,然后返回结果列表。

一些其他答案在循环的每次迭代中都有一个if检查。

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;
            }
        }
    }
}

2
投票

这很容易写:

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
投票

这里是一个示例,可以更好地控制插入其他项目:


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);

-2
投票

[如果您想知道如何实现它,我会这样做:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.