Добавление / объединение двух 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) представляют собой операцию, которая каким-то образом преобразует экземпляр TOneTTwo, соответственно) в экземпляр 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();
}