Laden...

Bestimmte Elemente aus IEnumerable auswählen: Enumerable.Single/First/Where

Erstellt von Tholi vor 12 Jahren Letzter Beitrag vor 12 Jahren 4.132 Views
T
Tholi Themenstarter:in
18 Beiträge seit 2009
vor 12 Jahren
Bestimmte Elemente aus IEnumerable auswählen: Enumerable.Single/First/Where

Moinsen,

bin gerade dabei, weiter durch die Einschärnkungen der Ausgabe durch zu steigen.

Folgender Code:

List<string> fruits =
                   new List<string> { "apple", "passionfruit", "banana", "mango", 
                                "orange", "blueberry", "grape", "strawberry" };

      fruits.Add("test");
      IEnumerable<string> query = fruits.Where(fruit => fruit.Length < 6).Single();

      foreach (string fruit in query)
      {
        Console.WriteLine(fruit);
      }

Ist nichts besonderes, reicht mir aber erstmal zu verstehen.

ich versuche hier die Methode Single mit anzuwenden. Doch leider gelingt mir das nicht so, wie ich mir das vorstelle. (Das es einen Fehler in der Runtime geben sollte ist klar, da mehr als ein Item übrig bleibt.)

Habe auch schon:

 IEnumerable<string> query = fruits.Where(fruit => fruit.Length < 6).Single<string>();

probiert. Fehlermeldung, die bei obigen heraus kommt ist:

Fehlermeldung:
Eine implizite Konvertierung vom Typ "string" in "System.Collections.Generic.IEnumerable<string>" ist nicht möglich.

Frage die sich mir stellt, wie konvertiere ich ihm das nun richtig?

Im MSDN habe ich da bisher leider nichts gefunden, was mir weiter geholfen hat, bin für jeden Tipp dankbar.

Gruß

1.552 Beiträge seit 2010
vor 12 Jahren

Hallo Tholi

dafür gibt es mehrere Möglichkeiten.
fruits.Where(fruit => fruit.Length < 6).First();
fruits.Single(fruit => fruit.Length < 6);

Achtung. Bei Single darf die Ergebnismenge welche durch die Bedingung (fruit.Lenght <6) zurückgegebenwird nur genau 1 sein. Wenn 0 oder 1 nimm [...].SingleOrDefault()

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

1.130 Beiträge seit 2007
vor 12 Jahren

Frage die sich mir stellt, wie konvertiere ich ihm das nun richtig?

Wie wärs mit garnicht?

Entweder fu willst ein einzelnes Element, dann ist das vom Typ string,
oder du willst ne liste aller Elemente, dann lass einfach das .Single weg und du hast IEnumerable<string> als Ergebnis...

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

1.002 Beiträge seit 2007
vor 12 Jahren

Hallo zusammen,

der Vollständigkeit halber: James Michael Hare hat vor kurzem den Blogpost C#/.NET Little Wonders: First() and Single() - Similar Yet Different passend zum Thema verfasst. Darin werden die Unterschiede der beiden Erweiterungsmethoden sehr gut erklärt.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

T
Tholi Themenstarter:in
18 Beiträge seit 2009
vor 12 Jahren
IEnumerable<string> query = fruits.SingleOrDefault(fruit => fruit.Length < 6);

Hatte ich vorhin auch probiert gehabt und leider auch beim Compilieren folgenden Fehler bekommen:

Fehlermeldung:
Eine implizite Konvertierung vom Typ "string" in "System.Collections.Generic.IEnumerable<string>" ist nicht möglich.

Hatte leider noch nicht geholfen. 😦

@Floste: Prinzip geb ich dir Recht. Versuche die Ausgabe auf ein Element gerade herunter zu schrauben.

@m0rius: Sehe ich das falsch oder ist das ein wenig anders? Meine ich habe hier nen IEnumerable.

1.002 Beiträge seit 2007
vor 12 Jahren

Hallo Tholi,

überleg mal genau, was du da gemacht hast, dann wird dir auch auffallen, warum das gar nicht funktionieren kann: Du versuchst, alle Früchte, deren "Länge" echt kleiner als 6 ist, in query abzuspeichern. Soweit okay — nur wirst du dafür Where() verwenden müssen, da es sich eben nicht um eine einzelne Frucht handelt.

Genau dafür sind Single() und SingleOrDefault() allerdings gedacht, nämlich zum Zurückgeben des einzigen Elementes einer Collection, das eine bestimmte Bedingung erfüllt (respektive null bei Verwendeung von SingleOrDefault(), wenn die Collection leer ist oder keine Elemente enthält, die die Bedingung erfüllen).

Ich verweise an dieser Stelle nochmal auf den oben genannten Blogpost von James Michael Hare!

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

1.552 Beiträge seit 2010
vor 12 Jahren

Wenn du in der Doku nachgesehen hättest würdest du wissen dass Single auf eine Collection von Strings nur einen String zurückgibt, und weil die Methode Single heißt wird logischerweise eben nur 1 Element zurückgegeben.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

T
Tholi Themenstarter:in
18 Beiträge seit 2009
vor 12 Jahren

*Kopf -> Tisch*

@xxMUROyy: Danke für die kleine aber feine Erinnerung.

Ist es denn möglich den Rückgabewert wieder in ein IEnumerable<string> herein zu schreiben? Oder muss ich das dann über .Add() realisieren?

Hatte gehofft gehabt, dass es auf meinem Wege funktionieren könnte.

1.130 Beiträge seit 2007
vor 12 Jahren

Ist es denn möglich den Rückgabewert wieder in ein IEnumerable<string> herein zu schreiben? Oder muss ich das dann über .Add() realisieren?

new string[1]{wert}

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

1.552 Beiträge seit 2010
vor 12 Jahren

Ist es denn möglich den Rückgabewert wieder in ein IEnumerable<string> herein zu schreiben?

Nein mit Single/SingleOrDefault nicht, aber wie m0rius sagte mit Where.
Wie es Floste sagte ginge es auch, das könnte man dann mit dem Single kombinieren, und dann bist du dir sicher dass die Collection nur ein Element hat.
Aber warum so kompliziert. Auch wenn Single ein Element zurückgibt kannst du doch dieses einer bestehenden Collection hinzufügen.

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

2.891 Beiträge seit 2004
vor 12 Jahren

new string[1]{wert}

Oder noch kürzer: new [] { wert }

Wenn du nur ein einziges Element, aber dennoch als Auflistung, haben möchtest, kannst du dir mal die Enumerable.Take(TSource)-Methode (System.Linq) angucken.

S
417 Beiträge seit 2008
vor 12 Jahren

Ist es denn möglich den Rückgabewert wieder in ein IEnumerable<string> herein zu schreiben?

Dann mach doch gleich einfach:

fruits.Where(fruit => fruit.Length < 6).Take(1).ToList();
T
Tholi Themenstarter:in
18 Beiträge seit 2009
vor 12 Jahren
 IEnumerable<string> query = new []{fruits.SingleOrDefault(fruit => fruit.Length == 3)};

Das läuft jetzt auch. 😃

Das andere Methoden wie zum Beispiel Where() sinnvoller in manchen Fällen ist, ist klar. Brauchte das für mich zum Verständnis.

Vielen Dank an die zahlreichen Antworten. 😃

1.552 Beiträge seit 2010
vor 12 Jahren

Wobei ich dann in diesem Beispiel nicht verstehe warum du nicht Where benutzt. So hast du im schlimmsten Fall eine String Collection mit einem leeren String. Bei anderen Objecten null, was schlimm ist wenn du direkt mit der Collection weiterarbeitest. Warum nicht sofort Where nehmen wenn du indirekt genau dies machst.
Meine Frage noch: Warum nicht Single und dieses Single einer anderen Collection adden:
string s = [...].Single([...]);
myCollection.Add(s);
Wäre sicherlich optisch ansprechender und macht den selben Dienst

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

T
Tholi Themenstarter:in
18 Beiträge seit 2009
vor 12 Jahren

Könnte passieren. Da das gerade nur so ein kleines Testsnippet war, ist das nicht weiter problematisch. Wollte mir genauer anschauen wie das mit Single() funktioniert 😉