在整数列表的列表中查找重复项

Finding duplicate in a list of a list of integers

在整数列表的列表中查找重复项的最佳方法是什么(无论它们位于什么位置)?我不需要代码只是解决这个问题的最佳方法(在 C# 中)。

例如:

List<List<int>> TestData = new List<List<int>>
{
     new List<int> { 1, 2, 3 },
     new List<int> { 2, 1, 3 },
     new List<int> { 6, 8, 3, 45,48 },
     new List<int> { 9, 2, 4 },
     new List<int> { 9, 2, 4, 15 },
};

想法是这将 return

   Count | Set
----------------
   2x    | 1,2,3
   1x    | 6, 8, 3, 45, 48
   1x    | 9,2,4
   1x    | 9, 2, 4, 15

我一直在为这个看似非常简单的问题而烦恼,但由于某种原因我无法弄清楚。希望有人能够提供帮助,就像我说的代码不是必需的,但非常感谢。

嗯,首先你想把你的列表转换成集合,

var testSets = testData.Select(s => new HashSet<int>(s));

然后您可以将集合分组以实现相等。

var groupedSets = testSets.GroupBy(s => s, HashSet<int>.CreateSetComparer());

这里是fully working example,

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

public class Test
{
    public static void Main()
    {
        var testData = new List<List<int>>
        {
             new List<int> { 1, 2, 3 },
             new List<int> { 2, 1, 3 },
             new List<int> { 6, 8, 3, 45, 48 },
             new List<int> { 9, 2, 4 },
             new List<int> { 9, 2, 4, 15 }
        };

        var testSets = testData.Select(s => new HashSet<int>(s));

        var groupedSets = testSets.GroupBy(s => s, HashSet<int>.CreateSetComparer());

        foreach(var g in groupedSets)
        {
            var setString = String.Join(", ", g.Key);
            Console.WriteLine($" {g.Count()} | {setString}");
        }
    }
}

您应该使用适当的数据结构来执行您的要求。在这种情况下,您有一个集合到整数的字典:

IDictionary<ISet<int>, int>

如果您不想使用 LINQ(这可能是最佳实践,请参阅其他答案),您可以按如下方式构建它:

var result = new Dictionary<HashSet<int>, int>();

foreach (var i in TestData)
{
    var key = new HashSet<int>(i);

    int count;

    result.TryGetValue(key, out count);
    result[id] = count + 1;
}

尝试以下操作:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<List<int>> TestData = new List<List<int>>
            {
                 new List<int> { 1, 2, 3 },
                 new List<int> { 2, 1, 3 },
                 new List<int> { 6, 8, 3 },
                 new List<int> { 9, 2, 4 },
            };

            var values = TestData.SelectMany(x => x).GroupBy(x => x).ToList();
            var counts = values.Select(x => new { value = x.Key, times = x.Count() }).ToList();

            var times = counts.GroupBy(x => x.times).Select(x => new { key = x.Key, values = x.Select(y => y.value).ToList() }).OrderBy(x => x.key).ToList();

        }

    }

}
 The answer of @Jodrell is very elegant (for me is the best), but only say depends of what you want the answer is correct

    For the nex data
                var testData = new List<List<int>>
            {
                 new List<int> { 1, 2, 3 },
                 new List<int> { 1, 2, 3 },
                 new List<int> { 1, 2, 3, 3 },
            }

    The result is going to be:

    Count | Set

    3x |  1,2,3

    And not the next:

    Count | Set

    2x    | 1,2,3

       1x    | 1,2,3,3

    So depends of your question...


    Ok, so, with the last one this is my code, is not fancy and you can improve a lot of things
    enter code here


 using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace TestListInt
    {
        class Program
        {
            public class WrapperListInt
            {
                public List<int> list;
                public WrapperListInt(List<int> list)
                {
                    this.list = list;
                }

                public override int GetHashCode()
                {
                    return 0;
                }
                public override bool Equals(object obj)
                {
                    if (this == obj) return true;
                    WrapperListInt o = obj as WrapperListInt;
                    if (this.list.Count != o.list.Count) return false;

                    for (int i = 0; i < this.list.Count; i++)
                    {
                        if (this.list[i] != o.list[i]) { return false; }
                    }

                    return true;
                }
            }
            public Program() {
                var testData = new List<List<int>>
            {
                 new List<int> { 1, 2, 3 },
                 new List<int> { 1, 3, 2 },
                 new List<int> { 1, 2, 3, 3 },
                 new List<int> { 6, 8, 3, 45,48 },
                 new List<int> { 9, 2, 15, 4 },
                 new List<int> { 9, 2, 4},
                 new List<int> { 9, 2, 4, 15 }
            };

                //Order every list
                foreach (var td in testData)
                {
                    td.Sort();
                }


                Dictionary<WrapperListInt, int> dic = new Dictionary<WrapperListInt, int>();
                foreach (var listInt in testData)
                {
                    WrapperListInt aux = new WrapperListInt(listInt);
                    int countList;
                    if (dic.TryGetValue(aux, out countList))
                    {
                        dic[aux]++;
                    }
                    else
                    {
                        dic.Add(aux, 1);
                    }
                }

                foreach (var d in dic)
                {
                    var setString = String.Join(", ", d.Key.list);
                    Console.WriteLine($" {d.Value} | {setString}");
                }
            }
            static void Main(string[] args)
            {
                new Program();
            }
        }
    }