13

我正在编写一个小程序来比较两个列表。如果值相同,我将它们添加到列表 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

我会使用IntersectandExcept方法:

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

如果将返回列表{4, 7, 10, 11}而不是仅返回{7, 11}.

它不会删除 4 的值,因为当我删除 2 的值时,(对于i=0nums列表来自

//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如果您尝试这样做,该语句将引发异常。在这种情况下,您可以使用一段时间

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 回答
3

您需要在两者中找到缺失的元素:

List<int> onlyInA = groupA.Except(groupB).ToList();
List<int> onlyInB = groupB.Except(groupA).ToList();

或在单个 linq 中:

List<int> missing = groupA.Except(groupB).Union(groupB.Except(groupA)).ToList()

注意 - 与所有 linq 一样,值得指出的是,它不是最有效的方法。所有列表迭代都有成本。如果列表真的很大,那么对两个列表进行排序然后一起迭代它们会更快......

于 2020-10-03T04:24:46.617 回答
-1

问题的标题是“比较两个列表”,一些只对真/假结果感兴趣的人会进入该问题

使用 Enumerable.SequenceEqual 方法

    if (listA.SequenceEqual(listB))
    {
       // they are equal
    }
于 2021-12-02T18:03:36.607 回答