2016-07-26 8 views
1

Ich habe eine Liste mit Strings:Linq Aggregat auf akkumulierte Bool-Wert

List<string> strList = new List<string>(); 

strList.Add("first"); 
strList.Add("second"); 
strList.Add("third"); 
strList.Add("fourth"); 

Ich brauche zwei Strings bis zu einem gewissen Verfahren bei jeder Iteration zu senden, die bool und schließlich sagen gibt, was das Ergebnis war.

Zum Beispiel:

  • Erste Iteration: "erste", "zweite" (liefert true)
  • Zweite Iteration: "zweite", "dritte" (liefert true)
  • dritte Iteration: "dritter", "vierte" (false zurück)

So Wert zurück aus allen Anrufen ist false (performing "&&" zwischen diesen Rückgabewerten).

Ich habe LINQ zu verwenden, so habe ich versuchen, so etwas wie zu tun:

strList.Aggregate<bool>((prev, current) => Method(prev,current)); 

aber leider etwas mache ich falsch.

Weitere Erläuterungen:

Ich möchte Bool Methode aufrufen (string, string) für alle aufeinander folgenden String-Paaren in strlist und erhalten die boolean & & aller Ergebnisse

+0

Verbessern Sie Ihre Spezifikationen. "Der Rückgabewert aller Aufrufe ist also falsch". Doch die erste und zweite Iteration sind wahr. –

+1

@HaraldDutch: OP möchte 'bool Methode (string, string)' für alle aufeinander folgenden 'string' Paare in' strList' aufrufen und die boolesche '&&' aller Ergebnisse erhalten. – Groo

+1

Nur um zu klären, möchten Sie kurzschließen (d. H. Bewertung nach dem ersten "false" -Wert stoppen) oder bis zum Ende der Liste auswerten und das Endergebnis zurückgeben? – Groo

Antwort

4

Ein Weg, um sein könnte schaffen die Paare und Enumerable.All rufen sie dann zu sehen, ob einer von ihnen falsch ist:

// create tuples 
var pairs = strList 
    .Zip(strList.Skip(1), Tuple.Create); 

// check if all are true 
var result = pairs.All(p => Method(p.Item1, p.Item2)); 

Doch diese Kurz circuting ist (wird s top Bewertung nach dem ersten false ist aufgetreten), und nach der Bearbeitung scheint es, Sie wollen die gesamte Liste zu bewerten.

In diesem Fall können Sie Aggregate<Tuple<string>, bool> verwenden (d. H. Die Überladung, die einen Akkumulator eines anderen Typs hat), nachdem Sie die Tupel haben. Beginnen Sie mit true, und verwenden Sie die boolean &:

var finalResult = strList 
    .Zip(strList.Skip(1), Tuple.Create) 
    .Aggregate(true, (val, tuple) => Method(tuple.Item1, tuple.Item1) & val); 

Wenn Ihre Methode eine Tuple akzeptieren würde, wäre es vielleicht etwas mehr lesbar sein.

+0

Das unglückliche Bit über die Verwendung von LINQ für diese benachbarten Typvergleiche ist, dass die Implementierung selten kurzschließt. 'Alle' werden gestoppt, sobald sie einen Fehler gefunden haben, aber nicht bevor Sie die gesamte Sammlung in Paare gepackt haben. – Derpy

+0

@ Chee'Burgers: Warum sagst du es "selten" Kurzschlüsse? Ganz im Gegenteil, LINQ ist in all seinen Methoden faul, und nach dem ersten 'false' Ergebnis werden keine Tupel erzeugt (natürlich im ersten Beispiel). Genau wie "Paare" an sich nichts auswerten wird. Oder beispielsweise 'pairs.First()' erstellt nur ein einzelnes Tupel. – Groo

+0

'&' funktioniert, aber '&&' wäre hier besser geeignet. – Kit

0

Dieses Verfahren verwendet eine different overload von Aggregate und vermeidet die Zip(), aber vorausgesetzt, dass Sie Code Method so die anfängliche leere Zeichenfolge zu handhaben als der geimpften Tupel getrennt.

 var result = strList.Aggregate(
      Tuple.Create("", true), 
      (val, current) => Tuple.Create(current, val.Item2 & Method(val.Item1, current)), 
      val => val.Item2); 

Sie können dies bei der Arbeit sehen this .NET Fiddle verwenden. Es behandelt nicht einen Fall von nur 1 Element in der Liste, aber auch die akzeptierte Antwort nicht. Ich denke, wir können davon ausgehen, dass das irgendwo durch einen Scheck geschützt wird.