2つの汎用リストListがあり、Place.Idプロパティに基づいてすべての一意のPlaceオブジェクトを1つのListにマージしたい場合、これを効率的に行うための良い方法は何ですか?
1つのリストには常に50が含まれ、もう1つのリストにはさらに多くが含まれる可能性があります。
result = list1.Union(list2, new ElementComparer());
IEqualityComparerを実装するには、ElementComparerを作成する必要があります。たとえば、これを参照してください
注:.NET3.5以降。
効率を強調したい場合は、自分でマージを行うための小さなメソッドを作成することをお勧めします。
List<Place> constantList;//always contains 50 elements. no duplicate elements
List<Place> targetList;
List<Place> result;
Dictionary<int, Place> dict;
for(var p in constantList)
dict.Put(p.Id,p);
result.AddRange(constantList);
for(var p in targetList)
{
if(!dict.Contains(p.Id))
result.Add(p)
}
独自のElementComparerを定義する必要がなく、ラムダ式を使用するだけの場合は、次のことを試すことができます。
List<Place> listOne = /* whatever */;
List<Place> listTwo = /* whatever */;
List<Place> listMerge = listOne.Concat(
listTwo.Where(p1 =>
!listOne.Any(p2 => p1.Id == p2.Id)
)
).ToList();
基本的に、これはEnumerable listOneをlistTwo内のすべての要素のセットと連結して、要素がlistOneとlistTwoの共通部分にないようにします。
速度が必要な場合は、ハッシュメカニズムを使用して比較する必要があります。私が行うことは、すでに読み取ったIDのハッシュセットを維持し、IDがまだ読み取られていない場合は、結果に要素を追加することです。必要な数のリストに対してこれを行うことができ、マージが完了する前に消費を開始したい場合は、リストの代わりにIEnumerableを返すことができます。
public IEnumerable<Place> Merge(params List<Place>[] lists)
{
HashSet<int> _ids = new HashSet<int>();
foreach(List<Place> list in lists)
{
foreach(Place place in list)
{
if (!_ids.Contains(place.Id))
{
_ids.Add(place.Id);
yield return place;
}
}
}
}
1つのリストに50の要素があり、もう1つのリストにさらに多くの要素があるという事実は意味がありません。リストが順序付けられていることを知らない限り...