9

私は2つのリストを持っています:list1そしてlist2(両方ともint型)

list2ここで、のコンテンツを削除したいと思いlist1ます。C#でこれを行うにはどうすればよいですか?

PS:ループを使用しないでください。

4

4 に答える 4

24

重要な変更

コメントで指摘されているように、.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ます。他の参照が更新を確認する必要がない場合は、そのために推奨されます。

于 2013-01-17T21:57:34.260 に答える
9
list1.RemoveAll(x => list2.Contains(x));
于 2013-01-17T21:58:08.193 に答える
5

あなたはこれを使うことができます:

List<T> result = list1.Except(list2).ToList();
于 2013-01-17T21:57:34.637 に答える
1

これにより、 :secondListからのすべてのアイテムが削除されます。firstList

firstList.RemoveAll( item => { secondList.Contains(item); } );
于 2013-01-17T22:15:34.003 に答える