Добавление / объединение двух IEnumerable последовательностей
У меня есть два комплекта datarows. Они каждый интерфейс IEnumerable. Я хочу добавить / объединить эти два списка в один список. Я уверен, что это выполнимо. Я не хочу делать цикл for и заметил, что в двух списках есть метод Union и метод Join. Есть идеи?
3 ответов
предполагая, что объекты одного типа, вы можете использовать либо 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
.
Я просто столкнулся с аналогичной ситуацией, когда мне нужно объединить несколько последовательностей.
естественно искал существующие решения в Google / StackOverflow, однако ничего не нашел, не оценил перечислимое, например, преобразовать в массив, а затем использовать Array.Copy()
etc. поэтому я написал расширение и статический метод utiltiy под названием 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;
}
}
на вступить метод похож на SQL-соединение, где список перекрестных ссылок на основе условия, это не конкатенация строк или добавление в список. The Союз метод делает то, что вы хотите, как и функция concat метод, но оба являются ленивыми оценками и имеют требование, чтобы параметры были ненулевыми. Они возвращают либо Конкатитератор, либо Юнионитератор, и если вызывается повторно, это может вызвать проблемы. Жаждущий оценка приводит к различному поведению, если это то, что вы хотите, тогда можно использовать метод расширения, подобный приведенному ниже.
public static IEnumerable<T> myEagerConcat<T>(this IEnumerable<T> first,
IEnumerable<T> second)
{
return (first ?? Enumerable.Empty<T>()).Concat(
(second ?? Enumerable.Empty<T>())).ToList();
}