2017-01-03 43 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