2009-09-03 11 views
0

Ich habe diese KlasseLinq-Abfrage für die Datenaggregation

public class Line 
{ 
    public string ConnectionsIndex{get;set;} 
} 

meine Linq Problem ist, dass ich diese Zeilen

var l1 = new Line{ ConnectionsIndex="01,02"}; 
var l2 = new Line{ ConnectionsIndex="02,03"}; 
var l3 = new Line{ ConnectionsIndex="01,03"}; 

in diesem

var l4 = new Line{ ConnectionsIndex="01,02,03"}; 

zu aggregieren haben Es ist möglich, zu tun mit Linq?

DETAIL:

Die Sache ist komplizierter (zumindest für mich), wenn ich die anderen Elemente hinzufügen, die ich in meiner Sammlung haben.

var l5 = new Line (ConnectionsIndex = "02,04"); 
var l6 = new Line (ConnectionsIndex = "03,06"); 

da gibt es nicht andere Leitungen mit den Paaren 03,04, 01,04, 01,06 und 02,06

Ich weiß nicht, ob ich es gut erklärt haben ...

in der Praxis, stellen Sie sich vor, Sie haben alle Punkte eines Polygons, ich möchte eine Zeile aller Elemente aus der Abfrage erhalten, indem Sie eine Liste der Verbindungen zwischen allen Punkten jedes Polygons geben.

(meine Liste enthält mehr als ein Polygon)

Ein Punkt sollte nicht in Folge aufgenommen werden, wenn nicht für alle anderen verbunden.

Dies ist ein Beispiel von meiner Liste Inhalt:

ConnectionsIndex="166,171" 
ConnectionsIndex="166,174" 
ConnectionsIndex="166,333" 
ConnectionsIndex="169,170" 
ConnectionsIndex="171,175" 
ConnectionsIndex="171,334" 
ConnectionsIndex="167,174" 
ConnectionsIndex="172,174" 
ConnectionsIndex="174,335" 
ConnectionsIndex="177,341" 
ConnectionsIndex="180,200" 
ConnectionsIndex="181,183" 
ConnectionsIndex="182,199" 
ConnectionsIndex="184,185" 
ConnectionsIndex="186,188" 
ConnectionsIndex="189,192" 
ConnectionsIndex="190,230" 
ConnectionsIndex="191,375" 

In dieser Liste haben Sie zum Beispiel ein Dreieck zwischen 166, 171 und 334

Mehr Detail:

var group = Linien .Where (x => x.ConnectionsIndex.Split (','). Enthält (line. ConnectionsIndex.Split (',') [0]) || x. ConnectionsIndex.Split (','). Enthält (Zeile ConnectionsIndex.Split (',') [1])). ToList(); if (group.Count() == 1) { straight_lines.Add (line); } sonst { // Hier habe ich eine "Gruppe" mit allen Linien zwischen dem Punkt .. I distinc Punkte }

+0

Hmm ... Ich fürchte, ich verstehe immer noch nicht, was Sie versuchen zu tun. Könnten Sie einige Beispiele (3 oder 4) von Sammlungen von Eingaben und der gewünschten Ausgabe geben? –

+0

Ich habe etwas versucht, aber für Ihre Beispieldaten gibt es "166,171,174,333,175,334,167,172,335". Müssen Sie die genauen Polygone bestimmen? – Botz3000

+0

Ich stimme zu, dass mehr Details erforderlich sind. Sind Ihre Werte "x, y" Koordinaten, und Sie versuchen, alle verbundenen Punkte zu einer Linie zu bilden? – MattH

Antwort

0

Dies ist schlechter Weg habe ich gefunden ... und es funktioniert!

var l = linee.Distinct(
      (a, b) => a.ConnectionsIndex == b.ConnectionsIndex,x=>x.ConnectionsIndex.GetHashCode()) 
     .ToList(); 

    var single_lines = new List<Linea>(); 
    var multiple_lines = new List<Linea>(); 
    foreach (var linea in l) 
    { 
     var group = l 
      .Where(x => x.ConnectionsIndex.Split(',').Contains(linea.ConnectionsIndex.Split(',')[0]) || 
       x.ConnectionsIndex.Split(',').Contains(linea.ConnectionsIndex.Split(',')[1])).ToList(); 
     if (group.Count()==1) 
     { 
      single_lines.Add(linea); 
     } 
     else 
     { 
      var indexes = new List<string>(); 
      var dist = group.Select(x => new {Index = x.ConnectionsIndex.Split(',').ToList()}).ToList();  

      foreach (var linea1 in dist) 
      { 
     indexes=indexes.Concat(linea1.Index).ToList(); 
      } 

      var indexstring = new StringBuilder(); 
      foreach (var s in indexes.Distinct().OrderBy(x=>Convert.ToInt32(x))) 
      { 
     indexstring.Append(s).Append(','); 
      } 
      indexstring.Remove(indexstring.Length - 1, 1); 
      multiple_lines.Add(new Linea() {ConnectionsIndex = indexstring.ToString()}); 
     } 
    } 

var multi_distinct=multiple_lines.Distinct(
      (a, b) => a.ConnectionsIndex == b.ConnectionsIndex, x => x.ConnectionsIndex.GetHashCode()) 
      .ToList(); 

linee = single_lines.Concat(multi_distinct).ToList(); 

Wenn Sie bessere Lösungen finden oder kennen, sind Sie willkommen!

1

So etwas bekommen wollen:

var connections = (from line in lines 
        from connection in line.Split(',') 
        select connection).Distinct() 
            .ToArray(); 

Line line = new Line { ConnectionsIndex = string.Join(",", connections) }; 

Dies gilt nicht bestellen Sie die Verbindungen, aber Sie können das leicht hinzufügen, wenn Sie es brauchen. anstelle eines einzelnen getrennten String

Dies wäre alles sauberer, wenn Sie zufrieden waren ConnectionsIndex als eine Sammlung von Zeichenketten zu haben, natürlich :)

+0

Ich muss es in Form von einzelnen begrenzten String haben, um es einfach mit NHibernate zu speichern ... Ich werde bald Ihren Hinweis überprüfen. –

+0

Sorry, aber es ist nicht die richtige Antwort ... Ich muss meine Frage bearbeiten und weitere Details hinzufügen. –

0

ich benutzten:

var l4 = new Line{ 
    ConnectionsIndex = 
     string.Join(",", (lines.SelectMany(x => x.ConnectionsIndex.Split(',')) 
           .Distinct() 
           .OrderBy(s => s)).ToArray()) 
}; 
+0

Es tut mir leid, aber es gibt die gleichen Ergebnisse wie die Jon Skeet One's –

0

Nur eine Anmerkung, die ich denke, was Sie suchen, ist eine Möglichkeit, maximale Cliquen zu finden (ein Konzept aus der Graphentheorie). Dies ist bekanntlich ein NP-schweres Problem. Ich denke, dass deine Version manchmal funktioniert, und hoffe auf die Fälle, die dich interessieren. Aber nicht für komplizierte Fälle, in denen irgendetwas mit etwas anderem verbunden sein kann. In der Tat, wenn Sie viele Knoten haben, sind diese Fälle nicht machbar, selbst bei großen CPU-Zyklus-Budgets (unabhängig von LINQ).

Verwandte Themen