2009-04-07 4 views
3

Ich habe ein list<list<string>>Jede Möglichkeit, einzigartige Aufzeichnungen mit Linq (C#) zu bekommen?

in list[x][0] Aufzeichnungen, aus denen ich eindeutige Datensätze also solche Aufzeichnung wählen mag nicht in einer anderen list[x][0] sein würde, wenn ich es wählen, ich würde list[x] ganze Reihe gerne gewählt werden . Ich habe nicht die entsprechende exapmple hierfür in Linq gefunden, bitte mich

Wenn Jon Skeet fragt zu klären :(

EDIT helfen, ich nicht ;-) leugnen

list<list<string>> 

enthält eine Liste von String-Tabellen. Jeder der Zeichenfolge "Tabelle" enthält mehrere Schlüssel und ich möchte eindeutige Datensätze aus der Liste-> Bedeutung ersten Element in dieser "Tabelle" erhalten.

So:

item[0] = "2","3","1","3" 
item[1] = "2","3","4","2" 
item[3] = "10","2" 
item[4]= "1","2" 

-> einzigartig würde bedeuten, dass ich Zeilen item[3] and item[4] so einzigartig ableiten kann. weil das erste Vorkommen von Nummer/String wichtig ist.

Wenn es zwei oder mehr Datensätze/Zeilen (item[x] of which first item (item[x][0]) mehr existiert als einmal in der Liste, es ist nicht eindeutig.

Erstes Element jeder Liste wichtig ist Eindeutigkeit zu bestimmen. Vielleicht würde es einfacher, wenn jemand sein kann helfen, einen Weg zu finden, nicht-unique -> so aus dem obigen Beispiel die Liste würde ich nur Artikel [0] und Artikel [1]

+0

list [x] [0] ist sicherlich eine einzelne Zeichenkette - wie kann diese Karte "aufnehmen"? Ich bin unklar ... –

Antwort

10

BEARBEITEN: Ich habe die UniqueBy Implementierung am unteren Rand aktualisiert wesentlich effizienter sein und nur einmal durch die Quelle iterieren

Wenn ich dich richtig verstanden habe ly (die Frage ziemlich unklar ist - es wäre wirklich hilfreich, wenn Sie ein Beispiel nennen könnte) das ist, was Sie wollen:

public static IEnumerable<T> OnlyUnique<T>(this IEnumerable<T> source) 
{ 
    // No error checking :) 

    HashSet<T> toReturn = new HashSet<T>(); 
    HashSet<T> seen = new HashSet<T>(); 

    foreach (T element in source) 
    { 
     if (seen.Add(element)) 
     { 
      toReturn.Add(element); 
     } 
     else 
     { 
      toReturn.Remove(element); 
     } 
    } 
    // yield to get deferred execution 
    foreach (T element in toReturn) 
    { 
     yield return element; 
    } 
} 

EDIT: Okay, wenn Sie nur über das erste Element der Liste für Einzigartigkeit Pflege, wir müssen es ändern etwas:

public static IEnumerable<TElement> UniqueBy<TElement, TKey> 
    (this IEnumerable<TElement> source, 
    Func<TElement, TKey> keySelector) 
{ 
    var results = new LinkedList<TElement>(); 
    // If we've seen a key 0 times, it won't be in here. 
    // If we've seen it once, it will be in as a node. 
    // If we've seen it more than once, it will be in as null. 
    var nodeMap = new Dictionary<TKey, LinkedListNode<TElement>>(); 

    foreach (TElement element in source) 
    { 
     TKey key = keySelector(element); 
     LinkedListNode<TElement> currentNode; 

     if (nodeMap.TryGetValue(key, out currentNode)) 
     { 
      // Seen it before. Remove if non-null 
      if (currentNode != null) 
      { 
       results.Remove(currentNode); 
       nodeMap[key] = null; 
      } 
      // Otherwise no action needed 
     } 
     else 
     { 
      LinkedListNode<TElement> node = results.AddLast(element); 
      nodeMap[key] = node; 
     } 
    } 
    foreach (TElement element in results) 
    { 
     yield return element; 
    } 
} 

Sie nennen würde es mit:

list.UniqueBy(row => row[0]) 
+0

ja ich will nur diejenigen, die nur einmal auftreten – Skuta

+0

Ich habe meine Frage mit mehr Informationen erneut – Skuta

+0

Hmm. Ich fürchte, ich verstehe es immer noch nicht. Interessiert Sie nur das erste Element jeder Liste? Bearbeiten, um das zu versuchen ... –

2

etwas Ähnliches, vielleicht?

Ich bin jetzt ziemlich sicher, dass dies für Sie arbeiten würde, da Ihre Klarstellung :)

var mylist = new List<List<string>>() { 
    new List<string>() { "a", "b", "c" }, 
    new List<string>() { "a", "d", "f" }, 
    new List<string>() { "d", "asd" }, 
    new List<string>() { "e", "asdf", "fgg" } 
}; 
var unique = mylist.Where(t => mylist.Count(s => s[0] == t[0]) == 1); 

unique enthält nun die „d“ und „e“ Einträge von oben.

List<List<string>> values; 
Dictionary<string, List<string>> index; 

Wenn Sie ein Element auf Werte hinzufügen, können Sie auch noch die Liste auf den Index mit der Zeichenfolge als Index:

+0

Ich denke, du hast es. Ich werde es überprüfen! :) – Skuta

+0

gibt es eine Chance zu Reservieren Sie es? also suche ich nach einem, einem Eintrag? : D – Skuta

+0

Wahrscheinlich .. Können Sie das ein bisschen mehr erklären? :) – Blorgbeard

0

Sie könnten eine Liste und einen Index/dictionary halten.

values[x].Add(newString); 
index[newString] = values[x]; 

Dann können Sie die richtige Liste erhalten von:

List<string> list = index[searchFor] 

Sie verlieren einige (minimal) Leistung und Speicher, wenn Erstellen des Index, aber man viel gewinnen, wenn die Daten abgerufen werden.

Wenn die Zeichenfolge nicht eindeutig ist, können Sie auch eine Liste> im dictionary/index speichern, um mehrere Ergebnisse pro Indexschlüssel zu ermöglichen.

Sorry nein Linq, das sieht nicht so cool aus, aber Sie haben eine schnelle Suche, und IMHO der Lookup-Code ist klarer.

+0

Kannst du mir mehr über diesen Ansatz erzählen? es sieht cool aus. – Skuta

0

Ich werde einfach weitermachen und diesen zum Kampf hinzufügen.

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

namespace ConsoleApplication1 { 
    class Program { 
     static void Main(string[] args) { 
      List<string> xx = new List<string>() { "xx", "yy", "zz" }; 
      List<string> yy = new List<string>() { "11", "22", "33" }; 
      List<string> zz = new List<string>() { "aa", "bb", "cc" }; 
      List<List<string>> x = new List<List<string>>() { xx, yy, zz, xx, yy, zz, xx, yy }; 
      foreach(List<string> list in x.Distinct()) { 
       foreach(string s in list) { 
        Console.WriteLine(s); 
       } 
      } 
     } 
    } 
} 
+0

Nach meiner Kenntnis von linq (fast keine) ist das nicht richtig. Bitte überprüfen Sie meinen Beitrag erneut :( – Skuta

+0

Gut mit den neuen Informationen in Ihrem Beitrag, es scheint mir, dass Sie die falsche Struktur verwenden, um Ihre Daten zu halten. Sie können besser mit einer Hashtabelle oder Datentabelle sein. – Ariel

+0

eigentlich, jetzt, dass ich Lesen Sie mehr nur eine gerade Anordnung. – Ariel

1

Hier ist etwas Linq für Sie.

List<List<string>> Records = GetRecords(); 
// 
List<List<string> UniqueRecords = Records 
    .GroupBy(r => r[0]) 
    .Where(g => !g.Skip(1).Any()) 
    .Select(g => g.Single()) 
    .ToList(); 
2

Hier ist der Code, den Sie benötigen. Es funktioniert perfekt für mich, um nur bestimmte Werte auszuwählen.

//distinct select in LINQ to SQL with Northwind 
var myquery = from user in northwindDC.Employees 
       where user.FirstName != null || user.FirstName != "" 
       orderby user.FirstName 
       group user by user.FirstName into FN 
       select FN.First();