简体   繁体   English

查找两个列表之间的差异数

[英]Find the number of differences between two lists

I want to compare two lists with the same number of elements, and find the number of differences between them. 我想比较两个具有相同元素数量的列表,并找出它们之间的差异数量。 Right now, I have this code (which works): 现在,我有以下代码(有效):

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

This feels messy to me, and it seems like there must be a more elegant way to achieve it. 这让我感到混乱,而且似乎必须有一种更优雅的方法来实现它。 Is there a way, perhaps, to combine the two lists into a single list of tuples, then simple examine each element of the new list to see if both elements are equal? 是否有办法将两个列表合并为一个元组列表,然后简单地检查新列表的每个元素以查看两个元素是否相等?

Since order in the list does count this would be my approach: 由于列表中的顺序确实算在内,这是我的方法:

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

Simply merging the lists using Enumerable.Zip() then summing up the differences, still O(n) but this just enumerates the lists once. 只需使用Enumerable.Zip()合并列表,然后将差异加总仍为O(n),但这只会枚举列表一次。

Also this approach would work on any two IEnumerable of the same type since we do not use the list indexer (besides obviously in your count comparison in the guard check). 同样,由于我们不使用列表索引器(显然在保护检查中的计数比较中也是如此),因此该方法也可以在相同类型的任何两个IEnumerable上使用。

Try something like this: 尝试这样的事情:

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

If order counts: 如果订单很重要:

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

I think your approach is fine, but you could use LINQ to simplify your function: 我认为您的方法很好,但是您可以使用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();
}

The way you have it written in the question, I don't think Intersect does what you're looking for. 您在问题中的书写方式,我认为Intersect不会满足您的需求。 For example, say you have: 例如,假设您有:

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

If you run list1.CountDifferences(list2) , I'm assuming that you want to get back 2 since elements 2 and 3 are different. 如果您运行list1.CountDifferences(list2) ,那么我假设您要取回2,因为元素2和3不同。 Intersect in this case will return 5 since the lists have 5 elements in common. 在这种情况下, Intersect将返回5,因为列表共有5个元素。 So, if you're looking for 5 then Intersect is the way to go. 因此,如果您要查找5,则Intersect是必经之路。 If you're looking to return 2 then you could use the LINQ statement above. 如果要返回2,则可以使用上面的LINQ语句。

You can use the extension method Zip of List. 您可以使用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

You want the Intersect extension method of Enumerable. 您需要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();
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM