13

2 つのリストを比較する小さなプログラムを作成しています。値が同じ場合は、それらを list dups に追加し、異なる場合は、distinct に追加します。値の一部が追加され、一部が追加されていないことに気付きました。しばらくデバッグした後、何が問題なのかわかりません。誰かが少し光を当てることができますか?ありがとう。

        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]);
        }
4

5 に答える 5

45

IntersectおよびExceptメソッドを使用します。

dups = groupA.Intersect(groupB).ToList();
distinct = groupA.Except(groupB).ToList();
于 2013-01-08T14:38:43.470 に答える
8

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

たとえば、次のコードは正しくありません

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]);
}

If は{4, 7, 10, 11}だけではなくリストを返し{7, 11}ます。

値 4 は削除されません。なぜなら、値 2 を削除すると、(for i=0)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 が 1 にインクリメントされ、次に参照される項目は ですnums[1]。これは、直感的に予想される 4 ではなく、6 です。したがって、実質的に 4 の値はスキップされ、チェックは実行されません。

反復しているコレクションを変更するときは、毎回非常に注意する必要があります。たとえば、foreachこれを試してもステートメントは例外をスローします。この場合、次のような while を使用できます

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
  }  
}

のように for をフォークすることもできます

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 を使用することもできます。

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

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();
于 2013-01-08T14:38:29.680 に答える
5

Linq で簡単に実行できます。

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

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

于 2013-01-08T14:39:10.140 に答える