2014-06-09 5 views
5

Ich bin auf der Suche nach einer Möglichkeit zur effizienten Umwandlung von Inhalt und Art der Sammlung.Scala Sammlungen: Inhalt und Art der Sammlung in einem Durchgang zu transformieren

Zum Beispiel map auf eine Set anwenden und das Ergebnis als List erhalten.

Beachten Sie, dass ich die Ergebnissammlung beim Anwenden der Transformation auf die Quellensammlung erstellen möchte (d. H. Ohne Zwischensammlung erstellen und dann in den gewünschten Typ transformieren).

Bisher habe ich mit diesem kommen (für Set wird in List umgewandelt, während jedes Element des set Inkrementieren):

val set = Set(1, 2, 3) 

val cbf = new CanBuildFrom[Set[Int], Int, List[Int]] { 
    def apply(from: Set[Int]): Builder[Int, List[Int]] = List.newBuilder[Int] 
    def apply(): Builder[Int, List[Int]] = List.newBuilder[Int] 
} 

val list: List[Int] = set.map(_ + 1)(cbf) 

... aber ich fühle mich wie sollte es mehr kurz und elegant Möglichkeit, dies zu tun (ohne manuell CanBuildFrom jedes Mal zu implementieren, wenn ich dies tun muss).

Irgendwelche Ideen, wie man das macht?

Antwort

7

Das ist genau das, was scala.collection.breakOut ist für-it'll zaubern die CanBuildFrom Sie benötigen, wenn Sie es die gewünschte neue Kollektion Art sagen:

import scala.collection.breakOut 

val xs: List[Int] = Set(1, 2, 3).map(_ + 1)(breakOut) 

Dies wird die Sammlung nur einmal durchlaufen. Weitere Informationen finden Sie unter this answer.

+1

wow das ist unglaublich gut kennt ! – Jean

1

Ich denke, dass dies tun, was Sie wollen, obwohl ich nicht 100% bin positiv, so vielleicht jemand bestätigen konnte:

(Set(1, 2, 3).view map (_ + 1)).toList 

view schafft, in diesem Fall eine IterableView, die, wenn Sie map nennen darauf führt das Mapping tatsächlich nicht durch. Wenn toList aufgerufen wird, wird die Map ausgeführt und eine Liste mit den Ergebnissen erstellt.

+0

Interessant ... das funktioniert und vermeidet das Problem, dass Sie z. '(Set (1, 2, 3) map (_% 2)). ToList', die doppelte Einträge löscht (dh das Ergebnis ist' List (1, 0) '' anstelle der erwarteten 'List (1, 0, 1) ', die Sie erhalten, wenn Sie die Ansicht verwenden). –

+0

@UrbanVagabond, Dies liegt daran, dass der erste Teil (Set (1, 2, 3) .view einen faulen Iterator erzeugt, wenn er die Map erstellt, erstellt er einen Satz (der die Duplikate nicht enthält) und erstellt danach die Liste Fall, wir erstellen einen neuen Satz und dann eine Liste, was er tun wollte, ist in einem Durchgang, sonst könnte er einfach Set (1, 2, 3) .toList.map (_ + 1) – igx