2017-02-19 8 views
5

Neu zu Scala. Ich wiederhole 100 mal eine for-Schleife. 10 mal will ich Bedingung 'a' erfüllt sein und 90 mal Bedingung 'b'. Allerdings möchte ich, dass die 10 a zufällig auftreten.Scala: For-Schleife, die Ints in einer Liste

Der beste Weg, den ich denken kann, ist ein Wert von 10 zufälligen Ganzzahlen zu erstellen, dann Schleife 1 bis 100 Ints.

Zum Beispiel:

val z = List.fill(10)(100).map(scala.util.Random.nextInt) 

z: List[Int] = List(71, 5, 2, 9, 26, 96, 69, 26, 92, 4) 

Dann so etwas wie:

for (i <- 1 to 100) { 
    whenever i == to a number in z: 'Condition a met: do something' 
else { 
    'condition b met: do something else' 
    } 
} 

ich versuchte, mit contains und == und =! aber nichts schien zu funktionieren. Wie sonst kann ich das tun?

+0

bin ich etwas fehlt oder nicht 'für (Ltg <- r = scala.util.Random.shuffle (List. fill (10) (wahr) + List.fill (90) (false))) {if (cond) ... else // nicht cond ...} 'do it? –

Antwort

5

Ihre Generation von Zufallszahlen könnte Duplikate ergeben ... ist das OK? Hier ist, wie man leicht 10 eindeutige Nummern erzeugen kann 1-100 (durch eine zufällig gemischt Sequenz von 1-100 zu erzeugen und den ersten zehn nehmen):

val r = scala.util.Random.shuffle(1 to 100).toList.take(10) 

Jetzt können Sie einfach einen Bereich von 1-100 in solche aufzuteilen, die sind in Ihrer zufällig generierte Liste enthalten sind, und diejenigen, die nicht sind:

val (listOfA, listOfB) = (1 to 100).partition(r.contains(_)) 

nun tun, was Sie mit den beiden Listen wollen, zB:

println(listOfA.mkString(",")) 
println(listOfB.mkString(",")) 

natürlich können Sie jederzeit einfach durchlaufen die Liste eins nach dem anderen:

(1 to 100).map { 
    case i if (r.contains(i)) => println("yes: " + i) // or whatever 
    case i => println("no: " + i) 
} 

Was Sie eigentlich für eine einfache Schleife halten, ist keine. Es ist ein Verständnis für das Verständnis und es ist eine Syntax Zucker, die zu verketteten Aufrufen von Karten, FlatMaps und Filtern entpackt. Ja, es kann genauso verwendet werden wie die klassische For-Schleife, aber nur weil List tatsächlich eine Monade ist. Ohne zu sehr ins Detail zu gehen, wenn Sie die idiomatische Scala-Methode (den "funktionalen" Weg) machen wollen, sollten Sie es vermeiden, klassische iterative for-Schleifen zu schreiben und lieber eine Sammlung Ihrer Daten erhalten und dann ihre Elemente zuordnen Führe aus, was immer du brauchst. Beachten Sie, dass Sammlungen eine wirklich umfangreiche Bibliothek enthalten, die es Ihnen ermöglicht, coole Methoden wie partition aufzurufen.

EDIT (auf Vollständigkeit):

Außerdem sollten Sie Nebenwirkungen oder zumindest schieben sie so weit auf dem Weg wie möglich vermeiden. Ich rede über das zweite Beispiel aus meiner Antwort. Nehmen wir an, Sie müssen das wirklich protokollieren (Sie würden einen Logger verwenden, aber println ist für dieses Beispiel gut genug). So etwas zu tun ist schlecht. Übrigens, Sie könnten foreach anstelle von map in diesem Fall verwenden, weil Sie keine Ergebnisse sammeln, nur die Nebenwirkungen durchführen.

Guter Weg wäre, die benötigten Sachen zu berechnen, indem man jedes Element in eine passende Schnur ändert. So berechnen die benötigten Strings und sammeln sie in results:

val results = (1 to 100).map { 
    case i if (r.contains(i)) => ("yes: " + i) // or whatever 
    case i => ("no: " + i) 
} 

// do whatever with results, e.g. print them 

Jetzt results enthält eine Liste von hundert „Ja x“ und „nein x“ Strings, aber du hast nicht das hässliche Ding machen und Protokollierung durchführen als Nebeneffekt im Mapping-Prozess.Stattdessen haben Sie jedes Element der Sammlung in eine entsprechende Zeichenkette gemappt (beachten Sie, dass die Originalsammlung intakt bleibt, wenn also (1 bis 100) in einem Wert gespeichert wurde, ist es immer noch da; Mapping erstellt eine neue Sammlung) und Sie können nun alles machen Du willst damit, zB Gib es an den Logger weiter. Ja, irgendwann müssen Sie "das hässliche Nebeneffekt-Ding" machen und das Zeug protokollieren, aber zumindest haben Sie einen speziellen Teil des Codes dafür, und Sie werden es nicht in Ihre Mapping-Logik mischen, die überprüft, ob Nummer ist in der Zufallssequenz enthalten.

+1

Netter Fang in Bezug auf mögliche Duplikate - das ist einer jener subtilen Fehler, die wahrscheinlich für eine Weile nicht bemerkt wurden :) – Eric

+0

Hah ja, vor allem in größeren Sammlungen – slouc

+1

Viel gelernt hier @slouc - schätzen diese umfassende Antwort :) – RDJ

3
(1 to 100).foreach { x => 
    if(z.contains(x)) { 
    // do something 
    } else { 
    // do something else 
    } 
} 

oder Sie können eine Teilfunktion verwenden, etwa so:

(1 to 100).foreach { 
    case x if(z.contains(x)) => // do something 
    case _ => // do something else 
}