我有两套数据行。它们都是IEnumerable。我想将这两个列表追加/连接到一个列表中。我确信这是可行的。我不想做一个for循环,并注意到两个列表上有一个Union方法和一个Join方法。有什么想法吗?
答案 0 :(得分:89)
假设您的对象属于同一类型,则可以使用Union
或Concat
。请注意,与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为止。