25

Giusto per chiarire, quando dico assigment multipla, assegnazione parallela, destrutturazione legano intendo il seguente pattern matching gemmaassegnazione multipla dei non tuple in scala

scala> val (x,y) = Tuple2("one",1) 
x: java.lang.String = one 
y: Int = 1 

che assegna "one"-x e 1-y.

stavo cercando di fare

val (x,y) = "a b".split() 

mi aspettavo che avrebbe tentato di scala modello abbinare la matrice con il modello, e sarebbe un'eccezione di runtime se la lunghezza della matrice non corrisponda alla lunghezza del modello.

Tutti i miei tentativi di convertire facilmente un Array in un Tuple2 erano inutili.

scala> Tuple2(Array(1,2):_*) 
<console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2) 
in object Tuple2 
     Tuple2(Array(1,2):_*) 
    ^

scala> Tuple2(Array(1,2).toList:_*) 
<console>:7: error: wrong number of arguments for method apply: (T1,T2)(T1, T2) 
in object Tuple2 
     Tuple2(Array(1,2).toList:_*) 

Esiste un modo pulito per utilizzare più assegnazioni con matrici o elenchi?

risposta

43

Tutto quello che dovete fare è rendere il vostro lato val (a sinistra del =) compatibile con il tuo inizializzazione (a destra della =):

scala> val Array(x, y, z) = "XXX,YYY,ZZZ".split(",") 
x: java.lang.String = XXX 
y: java.lang.String = YYY 
z: java.lang.String = ZZZ 

Come previsto, saranno gettati un scala.MatchError al runtime se la dimensione dell'array non corrisponde (non è 3, nell'esempio sopra).

+9

Funziona perché l'oggetto 'Array' include il metodo' unapplySeq', rendendolo utilizzabile come Pattern di Exractor. 'Array.unapplySeq (" XXX, YYY, ZZZ ".split (", ")' è chiamato, restituendo 'Some (ArrayBuffer (XXX, YYY, ZZZ))', che è un 'Some', e contiene tre elementi per associare a 'x',' y' e 'z'. – retronym

12

Poiché la stringa può avere contenuti arbitrari, non è possibile garantire il risultato di avere una forma a due tuple da parte del sistema di tipi (e nessuna conversione avrebbe senso). Quindi dovrai gestire le sequenze (come gli array).

Per fortuna ci sono right-ignoring sequence patterns che consentono comunque di abbinare i valori dei risultati.

val Seq(x, y, _ @ _*) = "a b".split(" ") 
+0

Mi chiedo: "Mi aspettavo che scala avrebbe tentato di associare l'array con il modello e genererebbe un'eccezione di runtime se la lunghezza dell'array non corrispondesse alla lunghezza del pattern", anche vedi la soluzione di Randall. Comunque anche questo è bello. Così semplice vorrei aver pensato a me stesso. +1. –

+0

In Scala 2.8, Array non è più Seq, quindi questa tecnica non funziona lì. –

+1

La tecnica funziona sicuramente, basta scrivere "Array" invece di "Seq". Oppure se puoi essere rilassato sulla fine della stringa, val Array (x, y) = "ab" diviso "" prendi 2 – extempore

6
 
scala> val Array(x, y, _*) = "a b" split " " 
x: java.lang.String = a 
y: java.lang.String = b