私は2つのリストを持っています:list1
そしてlist2
(両方ともint型)
list2
ここで、のコンテンツを削除したいと思いlist1
ます。C#でこれを行うにはどうすればよいですか?
PS:ループを使用しないでください。
重要な変更
コメントで指摘されているように、.Except()
は内部でセットを使用するため、の重複メンバーはlist1
最終結果に含まれません。
2つのシーケンスのセット差を生成します
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except(v=vs.110).aspx
ただし、O(N)であり、元のリストに重複を保持するソリューションがあります。除外セットを保持するためRemoveAll(i => list2.Contains(i))
にを使用するようにアプローチを変更します。HashSet<int>
List<int> list1 = Enumerable.Range(1, 10000000).ToList();
HashSet<int> exclusionSet = Enumerable.Range(500000, 10).ToHashSet();
list1.Remove(i => exclusionSet.Contains(i));
拡張メソッドToHashSet()
はMoreLinqで利用できます。
元の回答
Linqを使用できます
list1 = list1.Except(list2).ToList();
アップデート
好奇心から、私は自分のソリューションと@HighCoreのソリューションの簡単なベンチマークを行いました。
要素が1つしかないためlist2
、彼のコードは高速です。ますます大きくなるにつれてlist2
、彼のコードは非常に遅くなります。彼はO(N-squared)list1
(または、の各アイテムがの各アイテムと比較されるため、より具体的にはO(list1.length * list2.length))のように見えlist2
ます。私のソリューションのBig-Oをチェックするのに十分なデータポイントがありませんがlist2
、要素が少数以上ある場合ははるかに高速です。
テストに使用されるコード:
List<int> list1 = Enumerable.Range(1, 10000000).ToList();
List<int> list2 = Enumerable.Range(500000, 10).ToList(); // Gets MUCH slower as 10 increases to 100 or 1000
Stopwatch sw = Stopwatch.StartNew();
//list1 = list1.Except(list2).ToList();
list1.RemoveAll(i => list2.Contains(i));
sw.Stop();
var ms1 = sw.ElapsedMilliseconds;
更新2
このソリューションは、変数に新しいリストを割り当てますlist1
。@Толяが指摘しているように、オリジナルへの他の参照(存在する場合)はlist1
更新されません。RemoveAll
このソリューションは、最小サイズを除くすべてのサイズで大幅に優れていlist2
ます。他の参照が更新を確認する必要がない場合は、そのために推奨されます。
list1.RemoveAll(x => list2.Contains(x));
あなたはこれを使うことができます:
List<T> result = list1.Except(list2).ToList();
これにより、 :secondList
からのすべてのアイテムが削除されます。firstList
firstList.RemoveAll( item => { secondList.Contains(item); } );