2017-01-03 5 views
3

Wie finde ich die Duplikate in einer Liste mit Ganzzahlen (unabhängig davon, in welcher Position sie sich befinden)? Ich brauche nicht unbedingt Code, der am besten zu diesem Problem passt (in C#).Suchen nach Duplikaten in einer Liste mit Ganzzahlen

zB:

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

Die Idee ist, dass dies zurückkehren

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

Ich habe über diese scheinbar ganz einfache Frage mein Kopf wurde zu brechen, aber aus irgendeinem Grund kann ich nicht einen Reim aus. Hoffe jemand ist in der Lage zu helfen, wie ich sagte Code nicht notwendig, aber sehr geschätzt.

+5

Den besten Weg definieren - kürzester Code, optimale Leistung (und welche - Speicher/Geschwindigkeit)? –

+0

Sie können Wörterbuch oder Hashtable verwenden, um dies zu erreichen – Prabu

+0

Vielleicht sollten Sie 'Linq' versuchen ...' TestData.Select (L => L.Sort()). GroupBy (x => x) '=> Der zurückgegebene Wert ist gruppiert nach den Listen –

Antwort

6

gut, zuerst möchten Sie Ihre Listen-Sets, konvertieren

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

, dann können Sie Gruppen die Sätze für die Gleichstellung.

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

Hier ist ein 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

Danke für die elegante Lösung, aber das einzige Problem ist, dass ich auch die Länge der Sets vergleichen muss. Also sollte eine Liste wie {1,2,3}, {3, 1, 2} und {1,2,3,4} zurückkehren: 2x 1,2,3 und 1x 1,2,3,4 – John

+0

@John das wird passieren. '{1, 2, 3}' ist gleich '{3, 1, 2}', aber nicht '{1, 2, 3, 4}'. Sie können auf den Link für eine Demonstration klicken, – Jodrell

+0

Entschuldigen Sie Ihr Recht, ich machte einen Fehler in meinem eigenen Code – John

0

Sie die entsprechende Datenstruktur verwenden, sollten Sie Ihre Anforderungen zu erzwingen. In diesem Fall haben Sie ein Wörterbuch von Sätzen zu Ints:

IDictionary<ISet<int>, int> 

Wenn Sie nicht wollen, LINQ verwenden (was wahrscheinlich am besten Praxis, die anderen Antworten sehen) Sie es bauen können wie folgt:

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

Versuchen folgende:

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

Ich meinte die letzte – John

+0

@John Ich habe den Code, aber ich habe eine Sauerei mit dem Format, sorry. – user244943

Verwandte Themen