web-dev-qa-db-ja.com

2つのIEnumerable <T>をマージする

私は2つを持っています IEnumerable<T>s。

フォールバック要素で満たされます。これは常にほとんどの要素を含みます。もう1つは、いくつかのパラメーターに応じて塗りつぶされ、含まれる要素が少なくなる可能性があります。要素が2番目の要素に存在しない場合は、最初の要素と同等の要素で要素を埋める必要があります。

このコードは機能しますが、私には非効率的であり、IEnumerablesをIListsにキャストするか、一時リストを使用する必要があります。Personが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);  
}

助言がありますか?

43
Boris Callens

これを試して。

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)));
}
33
JaredPar
translated.Union(fallback)

または(PersonがIDでIEquatable<Person>を実装していない場合)

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;
    }
}
50
Jon Skeet

Concatを使用します。 Unionが機能しない場合List<dynamic>タイプ

0
smenon