2017-01-03 3 views
3

Каков наилучший способ найти дубликаты в списке списка целых чисел (независимо от того, в какой позиции находится)? Мне не нужен код, лучший способ решить эту проблему (в 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 }, 
}; 

Идея заключается в том, что это вернет

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

Я ломать голову над этим, казалось бы, очень простой вопрос, но по некоторым причинам я не могу понять вне. Надеюсь, кто-то может помочь, Как я уже сказал, код не нужен, но очень ценится.

+5

Определите лучший способ - кратчайший код, оптимальную производительность (и какой из них - память/скорость)? –

+0

Вы можете использовать словарь или хеш-таблицу для достижения этого – Prabu

+0

Возможно, вам стоит попробовать 'Linq' ...' TestData.Select (L => L.Sort()). GroupBy (x => x) '=> Возвращаемое значение равно сгруппированные по спискам –

ответ

6

хорошо, сначала вы хотите конвертировать ваши списки наборов,

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}"); 
     } 
    } 
} 
+0

Спасибо за элегантное решение, однако единственная проблема заключается в том, что мне также нужно сравнить длину наборов. Поэтому список, например {1,2,3}, {3, 1, 2} и {1,2,3,4} должен возвращать: 2x 1,2,3 и 1x 1,2,3,4 – John

+0

@John вот что произойдет. '{1, 2, 3}' равно '{3, 1, 2}', но не '{1, 2, 3, 4}'. Вы можете нажать на ссылку для демонстрации, – Jodrell

+0

Извините, что я допустил ошибку в своем собственном коде – John

0

Вы должны использовать соответствующие структуры данных для обеспечения ваших требований. В этом случае, у вас есть словарь наборов для Интс:

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

Попробуйте следующее:

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

     } 

    } 

} 
0
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(); 
      } 
     } 
    } 
+0

Я имел в виду последний – John

+0

@John Я поставил код, но я сделал беспорядок в формате, извините. – user244943