Autor |
Beitrag |
Vitalic
      
Beiträge: 68
|
Verfasst: So 05.09.10 18:14
Hallo Alle zusammen!
Ich habe ein kleines Problem beim Listen-Vergleich.
Es ist mir klar, dass man Listen anhand von Schleifen vergleichen könnte.
Beispielsweise so:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| for (int i = 0; i < feld1.Length; i++) { for (int j = 0; j < feld2.Length; j++) { if (feld1[i] == feld2[j]) { Console.WriteLine(feld1[i]); } } |
Aber was ist, wenn ich jetzt mehrere Listen habe?
Ich habe nicht die Lust noch weitere Schleifen zu verwenden, es muss doch eine Möglichkeit geben das ganze dynamisch zu gestalten...
Gruß
Vitalic
Moderiert von Christian S.: C#-Tags hinzugefügt
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 05.09.10 18:33
Zitat: | Aber was ist, wenn ich jetzt mehrere Listen habe? |
Man schreibt sich eine Methode, entsprechend deinem Code, die 2 Listen vergleicht und ruft die mehrmals auf.
Also wenn du z.B 3 Listen feld1, feld2, feld3 hast (ich finde es übrigens blöd Listen mit einem Singular zu benennen aus dem der Listencharacter nicht zwingend hervorgeht) und eine Methode z.B. Namens ListEquals dann wäre das
C#-Quelltext 1: 2:
| if ((ListEquals(feld1,feld2) && ListEquals(feld1,feld3)) ... |
Die üblichen Listentypen sollten übrigens bereits eine SequenceEqual Methode mitliefern (ab 3.5). Es gibt eigentlich keinen Grund eine eigene zu schreiben.
C#-Quelltext 1: 2:
| if (feld1.SequenceEqual(feld2) && feld1.SequenceEqual(feld3)) ... |
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: So 05.09.10 18:56
Danke, das ist sicherlich bessere Möglichkeit Listen zu vergleichen, aber so richtig dynamisch ist da ja auch nicht.
In meinem Fall könnte ich sogar mehr als 10 Listen haben und ich kann nie genau sagen wie viele es sind.
Es sind in jedem Fall mehr oder gleich 3 Listen.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: So 05.09.10 19:15
Wenn du mehrere Listen hast, so kannst du diese selber wieder in eine Liste packen, d.h.
C#-Quelltext 1:
| List<List<int>> lists = new List<List<int>>(); |
und statt 'int' dann deinen benötigten Datentypen einsetzen.
Wenn du dann jede Liste mit den anderen vergleichen willst, dann einfach eine 2-fache Schleife:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| for(int i=0; i<lists.Count; i++) for(int j=i+1; j<lists.Count; j++) { if(lists[i].SequenceEqual(lists[j])) { } } |
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: So 05.09.10 19:44
Ich habe jetzt mal anhand deines Beispiels versucht zu programmieren,
doch habe noch irgendwo einen Fehler, da keine Werte ausgegeben werden.
In XmlDevices habe ich jetzt mehrere Listen, welche mehrere Werte beinhalten.
Wenn es einen Wert gibt, der in allen anderen auch vorhanden ist, dann soll dieser ausgegeben werden.
private List<List<XmlDevices>> xmlDevices;
private List<XmlDevices> xmlDev;
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| for (int i = 0; i < xmlDevices.Count; i++) { for (int j = i + 1; j < xmlDevices.Count; j++) { if (xmlDevices[i].SequenceEqual(xmlDevices[j])) { xmlDev = new List<XmlDevices>(); xmlDev = xmlDevices[i]; for (int k = 0; k < xmlDev.Count; k++) { Console.WriteLine(xmlDev[k].getWert()); } } } } |
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 05.09.10 20:37
C#-Quelltext 1:
| Wenn es einen Wert gibt, der in allen anderen auch vorhanden ist, dann soll dieser ausgegeben werden. |
Könntest du noch mal genau ansagen was du vergleichen willst und was das Ergebnis dieses Vergleichs sein soll?
Ich hätte gedacht du willst den ganzen Listeninhalt vergleichen. Das macht SequenceEqual es vergleicht jeden Wert an der selben Position in beiden beteiligten Listen und wenn alle Werte gleich sind liefert SequenceEqual true. Du scheinst aber eine andere Art von Vergleich zu meinen.
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: So 05.09.10 22:19
Also, ich habe eine Liste, die mehrere Listen enthält. Nun möchte ich gucken, ob irgend ein Wert aus der ersten Liste mit den Werten aus den anderen Listen übereinstimmt. Es sollen nur die Werte aus der ersten Liste mit den Werten aus n anderen Listen verglichen werden. Beinhalten alle Listen den gleichen Wert, so wird er ausgegeben. SequenceEqual macht aber was anderes, denn damit klappt das nicht. Und wie bereits oben beschrieben ist, moechte ich das ganze dynamisch, denn in meiner Liste kann es mehrere Listen geben. Hoffe, dass das jetzt etwas genauer beschrieben ist.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: So 05.09.10 22:48
OK. Verstanden. Um geschickt gegen alle Listen in der Liste zu prüfen hilft dir die TrueForAll Methode.
Im Beispiel habe ich eine der Listen nicht mit in die Liste der Listen gepackt dann lässt sich das einfacher mit foreach anstatt einer for Schleife darstellen.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| List<int> values = new List<int>() { 1, 2, 5, 6, 7, 8 }; List<List<int>> listsOfValues = new List<List<int>>() { new List<int>() { 3, 4, 5, 6, 9, 0 }, new List<int>() { 1, 2, 5, 6, 9, 0 } };
foreach (var value in values) if (listsOfValues.TrueForAll(list => list.Contains(value))) Console.WriteLine(value); |
Für diesen Beitrag haben gedankt: Vitalic
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: Mo 06.09.10 10:48
Ralf Jansen hat folgendes geschrieben : | OK. Verstanden. Um geschickt gegen alle Listen in der Liste zu prüfen hilft dir die TrueForAll Methode.
Im Beispiel habe ich eine der Listen nicht mit in die Liste der Listen gepackt dann lässt sich das einfacher mit foreach anstatt einer for Schleife darstellen.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| List<int> values = new List<int>() { 1, 2, 5, 6, 7, 8 }; List<List<int>> listsOfValues = new List<List<int>>() { new List<int>() { 3, 4, 5, 6, 9, 0 }, new List<int>() { 1, 2, 5, 6, 9, 0 } };
foreach (var value in values) if (listsOfValues.TrueForAll(list => list.Contains(value))) Console.WriteLine(value); | |
Danke, das ist genau das was ich suche, jedoch bekomme ich keine Werte, wenn ich das in meine Variante überführe.
Das ist meine Variablendeklaration:
C#-Quelltext 1: 2:
| private List<List<XmlDevices>> xmlDevices; private List<XmlDevices> xmlDev; |
So kann ich z.B. alle Werte auslesen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| xmlDev = new List<XmlDevices>();
for (int i = 0; i < xmlDevices.Count; i++) { xmlDev = xmlDevices[i]; for (int j = 0; j < xmlDev.Count; j++) { Console.WriteLine(xmlDev[j].getWert()); } Console.WriteLine("\n"); } |
Nun versuche ich das Beispiel vom Ralf Jansen anzuwenden, bekomme aber keinen Wert zurück, obwohl alle Listen gleiche Werte beinhalten.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| xmlDev = xmlDevices[0]; for (int j = 0; j < xmlDev.Count; j++) { if (xmlDevices.TrueForAll(list => list.Contains(xmlDev[j]))) { Console.WriteLine(xmlDev[j].getWert()); } } |
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 06.09.10 10:54
Hallo,
hat die Klasse 'XmlDevices' denn eine passende Equals-Methode? Ansonsten würden nur die Referenzen verglichen (ich nehme mal an XmlDevices ist eine Klasse und keine Struktur (Wertetyp)).
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: Mo 06.09.10 11:09
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 06.09.10 13:31
Zitat: | Wozu benötige ich denn noch eine passende Equals-Methode?
Er prüft doch, ob die einzelnen Objekte gleich sind .. |
Eben und der Vergleich (in list.Contains) wird über die Equals-Methode gemacht.
Wenn du 2 mal 'new XmlDevices(wert)' für den selben wert machst werden die entstehenden XmlDevices Instanzen bei einer geerbten Standardimplementierung von Equals als unterschiedlich betrachtet. Wie Th69 schon geschrieben hat werden dann nur die Referenzen verglichen und diese sind nun mal unterschiedlich.
Siehe dazu auch die Guidelines wie Equals überschrieben werden sollte, man beachte insbesondere die Empfehlung auch GetHashcode in diesem Zug zu überschreiben.
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: Mo 06.09.10 14:28
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 06.09.10 14:54
Das ist wirklich "von hinten durch die Brust ins Auge" -)
Kannst du die Klasse "XmlDevices" selber nicht ändern, oder warum ignoriest du unsere Antwort bzgl. Equals?
Anstatt Contains könntest du auch Exists oder Find benutzen, um nach einem Element zu suchen (und dabei dann das Vergleichskriterium angeben):
C#-Quelltext 1:
| if (xmlDevices.TrueForAll(list => list.Exists(device => device.Property == value.Property))) |
wobei Property dann das entsprechende Vergleichskriterium wäre.
Für diesen Beitrag haben gedankt: Vitalic
|
|
Vitalic 
      
Beiträge: 68
|
Verfasst: Mo 06.09.10 15:28
|
|
|