简体   繁体   English

如何快速比较两个通用列表及其内容以检查它们是否相同?

[英]How shall I Quickly compare two generic lists and it's contents for checking if they are identical?

//Here I have a List of Lists //这里我有一个列表列表

List<List<T>> SelectionList = new List<List<T>>();

//My current code to compare lists //我当前用于比较列表的代码

    for(int i = 0; i < SelectionList.Count; i++)
    {
        for(int j = 0; j < SelectionList.Count; j++)
        {
            if (SelectionList[i].Equals(SelectionList[j]))
            {
                SelectionList.Remove(SelectionList[j]);
            }
        }
    }

// Note: The above code supposedly works, in cases where the contents of both the lists are ordered ie., they are in same index, but in my lists they might be same but list contents are shuffled. //注意:上面的代码应该可以工作,如果两个列表的内容都是有序的,即它们在同一个索引中,但在我的列表中它们可能相同但列表内容被打乱了。 in this case it fails to identify.在这种情况下,它无法识别。

//Basically I need to remove any repetitions of same list in my list of lists; //基本上我需要删除列表列表中相同列表的任何重复;

If, for each list, each possible value appears at most once in the list, you could use a Dictionary<T,int> to store how often an element appears.如果对于每个列表,每个可能的值在列表中最多出现一次,则可以使用Dictionary<T,int>来存储元素出现的频率。 Then you perform the following steps:然后执行以下步骤:

  1. Iterate over the lists, and, for each list, do the following: For each list element k , check if the dictionary contains it as a key.遍历列表,对于每个列表,执行以下操作: 对于每个列表元素k ,检查字典是否包含它作为键。 If it does not, then add key k with value 1 to your dictionary.如果没有,则将值为1的键k添加到您的字典中。 If it does, then increment the value for key k by 1 .如果是,则将键k的值增加1
  2. Iterate over the dictionary's elements and check that all values are 2 (if you have two lists) or n (if you have n lists).遍历字典的元素并检查所有值是否为2 (如果您有两个列表)或n (如果您有n列表)。

Your way is not correct, as you said, try this:如您所说,您的方式不正确,请尝试以下操作:

you should iterate the following procedure over your list-Of-Lists;您应该在列表列表中迭代以下过程;

private bool Compare(List<T> List1,List<T> List2)
{
   var infirstNotSecond = list1.Except(list2).ToList();
   var insecondNotFirst = list2.Except(list1).ToList();
   return !infirstNotSecond.Any() && !insecondNotFirst.Any();
}

If (and only if) the following is true:如果(且仅当)以下情况为真:

  • Your individual lists do not contain any duplicates您的个人列表不包含任何重复项
  • The type T of your list elements implements IComparable and GetHashCode() correctly列表元素的类型T正确实现IComparableGetHashCode()

Then you can remove each list that matches an earlier list like so (note that you must traverse the list backwards when removing items from the end of it otherwise the loop indices could go out of range):然后您可以像这样删除与较早列表匹配的每个列表(请注意,从列表末尾删除项目时必须向后遍历列表,否则循环索引可能超出范围):

for (int i = lists.Count - 1; i > 0; i--)
{
    for (int j = i - 1; j >= 0; j--)
    {
        if (!lists[i].Except(lists[j]).Any())
        {
            lists.RemoveAt(i);
            break;
        }
    }
}

The important line here is: !lists[i].Except(lists[j]).Any() .这里重要的一行是: !lists[i].Except(lists[j]).Any()

Let's break it down:让我们分解一下:

lists[i].Except(lists[j]) : - This produces a sequence of all the elements of lists[i] that are NOT in lists[j] , regardless of order. lists[i].Except(lists[j]) : - 这会产生 list[i lists[i]中不在 lists[ lists[j] ] 中的所有元素的序列,无论顺序如何。

Thus if all of the items in lists[j] are also in lists[j] , this will produce an empty sequence;因此,如果lists[j]中的所有项目也都在lists[j]中,这将产生一个空序列; otherwise, it will produce a non-empty sequence.否则,它将产生一个非空序列。

The .Any() will return true for a non-empty sequence, and false for an empty sequence. .Any()将为非空序列返回true ,为空序列返回false

So lists[i].Except(lists[j]).Any() will return false if the items are the same in each list and true if they differ.因此, lists[i].Except(lists[j]).Any()如果每个列表中的项目相同,则返回false ,如果它们不同,则返回true

This is the opposite of what we want for the lists.RemoveAt() so we just negate the result, giving the final code !lists[i].Except(lists[j]).Any() .这与我们想要的lists.RemoveAt()相反,所以我们只是否定结果,给出最终代码!lists[i].Except(lists[j]).Any()

Compilable console app:可编译的控制台应用程序:

using System;
using System.Collections.Generic;
using System.Linq;

static class Program
{
    static void Main()
    {
        var lists = new List<List<int>>
        {
            new() {1, 2, 3, 4, 5}, // [0]
            new() {2, 3, 4, 5, 6}, // [1]
            new() {3, 4, 5, 6, 7}, // [2]
            new() {5, 4, 3, 2, 1}, // [3] Dupe of [0]
            new() {4, 5, 6, 7, 8}, // [4]
            new() {6, 5, 4, 3, 2}, // [5] Dupe of [1]
            new() {5, 6, 7, 8, 9}, // [6] 
            new() {3, 4, 5, 2, 1}, // [7] Dupe of [0]
            new() {6, 7, 8, 9, 0}  // [8]
        };

        for (int i = lists.Count - 1; i > 0; i--)
        {
            for (int j = i - 1; j >= 0; j--)
            {
                if (!lists[i].Except(lists[j]).Any())
                {
                    lists.RemoveAt(i);
                    break;
                }
            }
        }

        for (int i = 0; i < lists.Count; ++i)
        {
            Console.WriteLine(string.Join(", ", lists[i]));
        }
    }

Try it on DotNetFiddle: https://dotnetfiddle.net/nWnOcP在 DotNetFiddle 上试试: https ://dotnetfiddle.net/nWnOcP

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

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