Finding duplicate in a list of a list of integers

763 views Asked by At

What is the best way to find the duplicates in a list of a list of integers (no matter what position thay are in)? I don't necessary need code just the best way to go about this problem (in C#).

eg:

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

The idea is that this will return

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

I've been breaking my head over this seemingly very simple question but for some reason I can't figure it out. Hope someone is able to help, Like I said code not necessary but greatly appreciated.

4

There are 4 answers

2
Jodrell On BEST ANSWER

well, first you want to convert your lists to sets,

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

then you can groups the sets for equality.

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

Here is a 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}");
        }
    }
}
0
sdgfsdh On

You should use the appropriate data-structure to enforce your requirements. In this case, you have a dictionary of sets to ints:

IDictionary<ISet<int>, int>

If you don't want to use LINQ (which is probably best-practice, see the other answers) you can construct it as follows:

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;
}
0
jdweng On

Try following :

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();

        }

    }

}
2
user244943 On
 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();
            }
        }
    }