Слияние двух IEnumerable‹T›

У меня два IEnumerable<T>.

Один наполняется запасными элементами. Этот всегда будет содержать наибольшее количество элементов. Другой будет заполняться в зависимости от некоторых параметров и, возможно, будет содержать меньше элементов. Если во втором элементе нет, мне нужно заполнить его эквивалентом первого.

Этот код выполняет свою работу, но мне кажется неэффективным и требует от меня приведения IEnumerables к IList или использования временного списка. Человек реализует IEquatable

IEnumerable<Person> fallBack = Repository.GetPersons();
IList<Person> translated = Repository.GetPersons(language).ToList();

foreach (Person person in fallBack)
{
    if (!translated.Any(p=>p.equals(person)))
        translated.add(person);  
}

Какие-либо предложения?


person Boris Callens    schedule 26.02.2009    source источник


Ответы (3)


Попробуй это.

public static IEnumerable<Person> SmartCombine(IEnumerable<Person> fallback, IEnumerable<Person> translated) {
  return translated.Concat(fallback.Where(p => !translated.Any(x => x.id.equals(p.id)));
}
person JaredPar    schedule 26.02.2009
comment
Это прекрасно работает, но есть нюанс, о котором вы должны знать: programmaticallyspeaking.com/ - person Oliver; 16.03.2015
comment
Я бы не стал использовать IEnumerable несколько раз. Под капотом он может повторно подключаться к БД или выполнять некоторые вычисления для каждого перечисления. Или, скажем, просто быть бесконечным... - person N. Kudryavtsev; 20.04.2019

translated.Union(fallback)

или (если Person не реализует IEquatable<Person> по ID)

translated.Union(fallback, PersonComparer.Instance)

где PersonComparer:

public class PersonComparer : IEqualityComparer<Person>
{
    public static readonly PersonComparer Instance = new PersonComparer();

    // We don't need any more instances
    private PersonComparer() {}

    public int GetHashCode(Person p)
    {
        return p.id;
    }

    public bool Equals(Person p1, Person p2)
    {
        if (Object.ReferenceEquals(p1, p2))
        {
            return true;
        }
        if (Object.ReferenceEquals(p1, null) ||
            Object.ReferenceEquals(p2, null))
        {
            return false;
        }
        return p1.id == p2.id;
    }
}
person Jon Skeet    schedule 26.02.2009
comment
Однако это будет работать только в том случае, если класс Person правильно реализует Equality. Судя по ОП, я предполагаю, что нет. - person JaredPar; 26.02.2009
comment
ХА-ХА! Джон, ты не мог бы упаковать это побольше чепухи? Я снова чувствую себя полным идиотом :P - person Boris Callens; 26.02.2009
comment
На самом деле они делают. OP также не содержит реального кода. Отчасти потому, что это упрощает мой вопрос, а отчасти потому, что мой босс боится размещать код в общественных местах: с - person Boris Callens; 26.02.2009
comment
@Jared: я был там :) - person Jon Skeet; 26.02.2009
comment
На самом деле, боюсь, это не то решение, к которому я стремился. Это даст мне коллекцию со ВСЕМИ элементами из обоих, и она никогда не попадет в мой метод Equals (Person other). Я что-то не так делаю или неправильно выразил свой вопрос? - person Boris Callens; 26.02.2009

используйте 1_. Union не работает в случае List<dynamic> типа

person smenon    schedule 01.01.2016