【问题标题】:Find the number of differences between two lists查找两个列表之间的差异数
【发布时间】:2011-04-23 05:07:01
【问题描述】:

我想比较两个具有相同数量元素的列表,并找出它们之间的差异数量。现在,我有这个代码(有效):

public static int CountDifferences<T> (this IList<T> list1, IList<T> list2)
{
    if (list1.Count != list2.Count)
        throw new ArgumentException ("Lists must have the same number of elements", "list2");

    int count = 0;
    for (int i = 0; i < list1.Count; i++) {
        if (!EqualityComparer<T>.Default.Equals (list1[i], list2[i]))
            count++;
    }

    return count;
}

这让我感觉很混乱,似乎必须有一种更优雅的方式来实现它。有没有办法,也许,将两个列表组合成一个元组列表,然后简单地检查新列表的每个元素,看看两个元素是否相等?

【问题讨论】:

    标签: c# linq list comparison


    【解决方案1】:

    由于列表中的顺序确实很重要,这将是我的方法:

    public static int CountDifferences<T>(this IList<T> list1, IList<T> list2)
    {
        if (list1.Count != list2.Count)
            throw new ArgumentException("Lists must have the same number of elements", "list2");
    
        int count  = list1.Zip(list2, (a, b) => a.Equals(b) ? 0 : 1).Sum();
        return count;
    }
    

    只需使用Enumerable.Zip() 合并列表,然后总结差异,仍然是 O(n),但这只是枚举列表一次。

    由于我们不使用列表索引器,因此这种方法也适用于任何两个相同类型的IEnumerable(显然除了在保护检查中的计数比较之外)。

    【讨论】:

    • Zip 正是我想要的。谢谢!
    【解决方案2】:

    我认为您的方法很好,但您可以使用 LINQ 来简化您的功能:

    public static int CountDifferences<T>(this IList<T> list1, IList<T> list2)
    {
        if(list1.Count != list2.Count)
            throw new ArgumentException("Lists must have same # elements", "list2");
        return list1.Where((t, i) => !Equals(t, list2[i])).Count();
    }
    

    按照您在问题中的写法,我认为 Intersect 不会满足您的要求。例如,假设您有:

    var list1 = new List<int> { 1, 2, 3, 4, 6, 8 };
    var list2 = new List<int> { 1, 2, 4, 5, 6, 8 };
    

    如果您运行list1.CountDifferences(list2),我假设您想要返回 2,因为元素 2 和 3 不同。 Intersect 在这种情况下将返回 5,因为列表有 5 个共同元素。因此,如果您正在寻找 5,那么 Intersect 是您的最佳选择。如果您希望返回 2,那么您可以使用上面的 LINQ 语句。

    【讨论】:

      【解决方案3】:

      试试这样的:

      var result = list1.Intersect(list2);
      var differences = list1.Count - result.Count();
      

      如果订单很重要:

      var result = a.Where((x,i) => x !=b[i]);
      var differences = result.Count();
      

      【讨论】:

      • 查看我对小贩回答的评论。对我来说,顺序很重要。
      • 编辑了我对订单问题的回复
      • 哦,太好了,我不知道Enumerable.Where 有这种超载。我将改用Enumerable.Zip,但这也有效!
      【解决方案4】:

      你想要 Enumerable 的 Intersect 扩展方法。

      public static int CountDifferences<T> (this IList<T> list1, IList<T> list2)
      {
          if (list1.Count != list2.Count)
              throw new ArgumentException ("Lists must have the same number of elements", "list2");
      
          return list1.Count - list1.Intersect(list2).Count();
      } 
      

      【讨论】:

      • 如果我错了,请纠正我,但我认为Intersect 提供了 set 交集(忽略顺序)。就我而言,顺序很重要。
      【解决方案5】:

      可以使用List的扩展方法Zip。

      List<int> lst1 = new List<int> { 1, 2, 3, 4, 5 };
      List<int> lst2 = new List<int> { 6, 2, 9, 4, 5 };
      int cntDiff = lst1.Zip(lst2, (a, b) => a != b).Count(a => a);
      
      // Output is 2
      

      【讨论】:

        猜你喜欢
        • 2015-03-19
        • 2016-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多