追加/连接两个IEnumerable序列

时间:2011-02-10 19:53:11

标签: c# ienumerable unions

我有两套数据行。它们都是IEnumerable。我想将这两个列表追加/连接到一个列表中。我确信这是可行的。我不想做一个for循环,并注意到两个列表上有一个Union方法和一个Join方法。有什么想法吗?

4 个答案:

答案 0 :(得分:89)

假设您的对象属于同一类型,则可以使用UnionConcat。请注意,与SQL UNION关键字一样,Union操作将确保消除重复项,而Concat(如UNION ALL)只会将第二个列表添加到最后第一个。

IEnumerable<T> first = ...;
IEnumerable<T> second = ...;

IEnumerable<T> combined = first.Concat(second);

IEnumerable<T> combined = first.Union(second);

如果它们属于不同的类型,那么你必须Select将它们变成常见的东西。例如:

IEnumerable<TOne> first = ...;
IEnumerable<TTwo> second = ...;

IEnumerable<T> combined = first.Select(f => ConvertToT(f)).Concat(
                          second.Select(s => ConvertToT(s)));

ConvertToT(TOne f)ConvertToT(TTwo s)表示以某种方式将TOne(和TTwo的实例)分别转换为T实例的操作。< / p>

答案 1 :(得分:2)

我刚遇到类似的情况,我需要连接多个序列。

自然搜索Google / StackOverflow上的现有解决方案,但是没有发现任何未评估可枚举的内容,例如转换为数组然后使用Array.Copy()等,所以我写了一个名为ConcatMultiple的扩展和静态实用方法。

希望这有助于任何需要这样做的人。

/// <summary>
/// Concatenates multiple sequences
/// </summary>
/// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
/// <param name="first">The first sequence to concatenate.</param>
/// <param name="source">The other sequences to concatenate.</param>
/// <returns></returns>
public static IEnumerable<TSource> ConcatMultiple<TSource>(this IEnumerable<TSource> first, params IEnumerable<TSource>[] source)
{
    if (first == null)
        throw new ArgumentNullException("first");

    if (source.Any(x => (x == null)))
        throw new ArgumentNullException("source");

    return ConcatIterator<TSource>(source);
}

private static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, params IEnumerable<TSource>[] source)
{
    foreach (var iteratorVariable in first)
        yield return iteratorVariable;

    foreach (var enumerable in source)
    {
        foreach (var iteratorVariable in enumerable)
            yield return iteratorVariable;
    }
}

/// <summary>
/// Concatenates multiple sequences
/// </summary>
/// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>        
/// <param name="source">The sequences to concatenate.</param>
/// <returns></returns>
public static IEnumerable<TSource> ConcatMultiple<TSource>(params IEnumerable<TSource>[] source)
{
    if (source.Any(x => (x == null)))
        throw new ArgumentNullException("source");

    return ConcatIterator<TSource>(source);
}

private static IEnumerable<TSource> ConcatIterator<TSource>(params IEnumerable<TSource>[] source)
{
    foreach (var enumerable in source)
    {
        foreach (var iteratorVariable in enumerable)
            yield return iteratorVariable;
    }
}

答案 2 :(得分:1)

Join方法类似于SQL连接,其中列表根据条件进行交叉引用,它不是字符串连接或添加到列表。 Union方法确实按照您所需的方式执行,Concat方法也是如此,但两者都是LAZY评估,并且要求参数为非null。他们返回ConcatIterator或UnionIterator,以及if called repeatedly this could cause problems。急切的评估会导致不同的行为,如果这是您想要的,那么可以使用如下所示的扩展方法。

error
259
259

答案 3 :(得分:0)

第二个及后续枚举的延迟调用

我通常使用Linq IEnumerable<T>.Concat(),但是今天我需要100%确保在处理完第一个枚举之后才对第二个枚举进行枚举。 (例如,两个我不想同时运行的数据库查询)。因此,以下函数使延迟枚举成为可能。

    IEnumerable<T> DelayedConcat<T>(params Func<IEnumerable<T>>[] enumerableList)
    {
        foreach(var enumerable in enumerableList)
        {
            foreach (var item in enumerable())
            {
                yield return item;
            }
        }
    }

用法:

    return DelayedConcat(
                () => GetEnumerable1(),
                () => GetEnumerable2(),
 // and so on.. () => GetEnumerable3(),
                );

在此示例中,GetEnumerable2函数的调用将被延迟,直到枚举GetEnumerable1为止。