2013-01-08 10 views
10

私は2つのリストを比較する小さなプログラムを書いています。値が同じ場合は、それらをリストダップに追加します。異なる場合は、それらを別名に追加します。私はいくつかの値が追加されていて、いくつかは追加されていないことに気付きました。しばらくの間デバッグした後、私はその問題が何であるか確信していません。誰かが少し光を当てることができますか?ありがとう。2つのリストを比較する<int>

 List<int> groupA = new List<int>(); 
     List<int> groupB = new List<int>(); 

     List<int> dups = new List<int>(); 
     List<int> distinct = new List<int>(); 

     groupA.Add(2); 
     groupA.Add(24); 
     groupA.Add(5); 
     groupA.Add(72); 
     groupA.Add(276); 
     groupA.Add(42); 
     groupA.Add(92); 
     groupA.Add(95); 
     groupA.Add(266); 
     groupA.Add(42); 
     groupA.Add(92); 


     groupB.Add(5); 
     groupB.Add(42); 
     groupB.Add(95); 

     groupA.Sort(); 
     groupB.Sort(); 

     for (int a = 0; a < groupA.Count; a++) 
     { 
      for (int b = 0; b < groupB.Count; b++) 
      { 
       groupA[a].CompareTo(groupB[b]); 


       if (groupA[a] == groupB[b]) 
       { 
        dups.Add(groupA[a]); 
        groupA.Remove(groupA[a]); 
        groupB.Remove(groupB[b]); 
       } 

      } 
      distinct.Add(groupA[a]); 
     } 
+0

期待した結果を投稿できますか? –

+0

あなたはすぐにグループ[b]を削除していると思います。あなたのためには、このA1のような作品 - > B 1 2 3 4 5 6 7など、A2 - > b1 2 3 4 5。あなたがbから数字を削除すると、dupsやdistinctに現れることはありません。しかし、それはちょうど私の本能です。 :) –

+0

ループの条件(要素番号に基づいて)が損なわれる可能性があるので、反復処理中にリストから要素を削除しています... – digEmAll

答えて

34

を行うことができ、私はIntersectExceptメソッドを使用します:あなたはLINQのでそれを簡単に行うことができます

dups = groupA.Intersect(groupB).ToList(); 
distinct = groupA.Except(groupB).ToList(); 
+1

Upvoted、素敵で簡単な解決策。 – PawelCz

+0

リストの長さが重要です。 var l1 = new List (){1、5、6}; var l2 = new List (){6、5、1、2}; l2.Except(l1)=> 2.l1.Except(l2)=> nothing –

8

リストからアイテムを削除すると、残りのエレメントのインデックスが下に移動します。 本質的に、forループを使用していくつかの項目をスキップしています。
whileループを使用してみて、アイテムを削除しないときに手動でカウンタをインクリメントしてください。例えば

だけではなく{7, 11}のリスト{4, 7, 10, 11}が返されます場合は、次のコードは、

List<int> nums = new List<int>{2, 4, 6, 7, 8, 10, 11}; 

for (int i = 0; i < nums.Count; i++) 
{ 
    if (nums[i] % 2 == 0) 
    nums.Remove(nums[i]); 
} 

間違っています。

I 2の値を削除するときにnumsリスト

//index 0 1 2 3 4 5 6 
nums = {2, 4, 6, 7, 8, 10, 11} 

//index 0 1 2 3 4 5 
nums = {4, 6, 7, 8, 10, 11} 

にループ終了から移行( i=0ため)、ので、4の値を削除しないであろうiは1にインクリメントされ、次に参照される項目は nums[1]であり、これは直感的には4ではないが4ではないが、実際には4の値はスキップされ、検査は実行されない。

反復処理するコレクションを変更するたびに、非常に注意してください。たとえば、foreachステートメントは、これを試しても例外をスローします。

distinct.AddRange(groupA); 
distinct.AddRange(groupB); 
distinct = distinct.Distinct().ToList(); 

:この場合、あなたは

for (int i = 0; i < nums.Count; i++) 
{ 
    if (nums[i] % 2 == 0) 
    { 
    nums.Remove(nums[i]); 
    i--; //decrement the counter, so that it will stay in place 
     //when it is incremented at the end of the loop 
    } 
} 

のような別の方法として、あなたはこのように、LINQを使用することができ、ためにも、フォークができますの

List<int> nums = new List<int>{2, 4, 6, 7, 8, 10, 11}; 

int i = 0; 
while (i < nums.Count) 
{ 
    if (nums[i] % 2 == 0) 
    { 
    nums.Remove(nums[i]) 
    }  
    else 
    { 
    i++; //only increment if you are not removing an item 
     //otherwise re-run the loop for the same value of i 
    } 
} 

のようにしばらく使用することができます

dups.AddRange(groupA); 
dups.AddRange(groupB); 

dups = dups.GroupBy(i => i) 
      .Where(g => g.Count() > 1) 
      .Select(g => g.Key) 
      .ToList(); 

なお、LINQ既存のgroupAおよびgroupBリストは変更されません。あなただけの明確な彼らにしたい場合は、あなただけの

groupA = groupA.Distinct().ToList(); 
groupB = groupB.Distinct().ToList(); 
+0

両方のループをwhileループに置き換えますか? – jpavlov

+0

私はあなたの実装を残しておきますが、コードがどこに間違っているか、そして修正する方法を示す例を追加しました。 – SWeko

4

を:

List<int> dups = groupA.Intersect(groupB).ToList(); 
    List<int> distinct = groupA.Except(groupB).ToList(); 

(あなたがしようとしていることを正しく理解していると仮定して)

関連する問題