2016-08-11 12 views
2

Ich habe eine Liste, die 1s und -1s enthält. Das Ziel, nach dem ich suche, ist, die Position in der Liste zu finden, wenn die Summe -1 ist.Wie finde ich die Position eines Wertes mit foldLeft aus einer Liste?

List[Int] = List(1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 
-1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1) 

Aber mein Code funktioniert nicht.

Hier sind meine Versuche (Ich habe den Code zum besseren Lesen entfernt) Hinweis: floor ist das val, das die Liste der Intents hält.

floor.foldLeft(0) { ((x,y) => x+y == -1) }.indexOf(-1) 

floor.foldLeft(0) ((x,y) => { (x + y == -1) {x.indexOf(-1)} } ) 

floor.foldLeft(0) { (x,y) => { if (x + y == -1) { indexOf(-1) } } } 

Ich würde gerne wissen, was ich hier falsch mache. Ich bin wirklich hinter dem Warum mehr als die Antwort an und für sich.

+0

Alle Ihre Lösungen verpassen einen wichtigen Punkt über FoldLeft. Der Wert "x" nimmt den Typ des Anfangswerts an, in diesem Fall "0", und der von der Funktion zurückgegebene Typ sollte diesen Typ haben. Im ersten Beispiel ist es boolesch. Die anderen beiden ergeben keinen Sinn. – pedrofurla

Antwort

2

Die anonyme Funktion (das zweite Argument zu foldLeft) muss denselben Typ wie das erste Argument zurückgeben.

Die Familien fold und reduce wurden entwickelt, um eine Sammlung zu erstellen und auf einen einzelnen Wert zu reduzieren. Es wird für dich hier nicht funktionieren.

Dies wird Sie bekommen, was Sie wollen.

floor.scanLeft(0)(_+_).indexOf(-1) - 1 // scan collection is 1 element longer 

In diesem Fall scan erzeugt eine neue Kollektion mit unterschiedlichen Eigenschaften/Werte, die für die Elemente von Interesse abgefragt werden können.


Also, wenn Sie wirklich Notwendigkeit foldLeft zu verwenden, dies versuchen.

floor.zipWithIndex.foldLeft((0,-1)) { 
    case ((s,x),(e,i)) => if (s+e == -1 && x < 0) (0,i) else (s+e, x) 
}._2 

ziemlich hässlich, weil Sie rund um die aktuelle Summe zu tragen haben, s, und der Index, wo Sie sind, i, und das aktuelle Element ausgewertet wird, e, und nachdem Sie Ihr Ziel finden, x, Sie halten Sie es herum und packen Sie es am Ende aus, ._2.

Vergleichen Sie das Ergebnis mit der scanLeft Version. Ich denke, Sie werden feststellen, dass die endgültige - 1 Anpassung erforderlich ist.

Hier ist ein weiterer Ansatz, der den Vorteil hat, früh abzusteigen, wenn das gewünschte Ziel erreicht wird.

val floorSums:Stream[Int] = Stream.tabulate(floor.length){ idx => 
    floor(idx) + (if (idx>0) floorSums(idx-1) else 0) 
} 

floorSums.indexOf(-1) // 38 
+0

Sind Sie sicher, dass indexOf (-1) für jedes Ereignis funktioniert? Das Element -1 erscheint mehrmals in der Sammlung. –

+0

Kluge Lösung ... – pedrofurla

+0

@MrD, der Wert "-1" erscheint zweimal in der resultierenden Scan-Sammlung. 'indexOf (-1)' gibt '39' zurück, was das erste Auftreten ist. – jwvh

2

Es gibt zwei Arten von Lösung für ein Problem wie diese, wo Sie benötigen teilweise durch eine Operation zu retten (in diesem Fall eine Falte).

Ein Stil ist eine nicht-lokale Rückkehr innerhalb eines def Sie nur für diesen Zweck schreiben zu verwenden (beachten Sie, dass .zipWithIndex jedes Element in ein Paar von Elementen dreht: das Original und der Index):

def exceedsTen(xs: List[Int]): Int = { 
    xs.zipWithIndex.foldLeft(0){ (sum, x) => 
    val now = sum + x._1 
    if (now > 10) return x._2 
    else now 
    } 
    -1 
} 

Der andere Stil soll einen Wert haben, den Sie weitergeben können, um anzuzeigen, dass Sie fertig sind - so dass Sie wirklich den ganzen Rest der Liste durchlaufen, aber Sie tun keine Arbeit, weil Sie wissen, dass Sie nicht haben zu.

def overTen(xs: List[Int]): Int = { 
    val pair = 
    xs.foldLeft((0, 0)){ (si, x) => 
     if (si._1 > 10) si 
     else (si._1 + x, si._2 + 1) 
    } 
    if (pair._1 > 10) si._2 else -1 
} 

In diesem Fall eine laufende Summe und den Index zu halten, wo man für ein wenig mehr Platz in Anspruch nimmt, was Sie gesucht haben gefunden, aber ist wohl ein wenig klarer, wenn Sie mit beiden Formen vertraut sind.

Im Allgemeinen ist es eine Art Nischenanwendung, Indizes zu finden; Sie wollen tun etwas nicht nur etwas finden und hängen an der Position für später.

+0

Wäre das nicht ein schöner Anwendungsfall für Streams? – pedrofurla

Verwandte Themen