2010-10-14 16 views
29

C'è qualcosa di simile a the slice notation in Python in Scala?Notazione Slice in Scala?

Penso che questa sia davvero un'operazione utile che dovrebbe essere incorporata in tutte le lingue.

+2

Bene, alcune persone preferiscono un linguaggio che rimanga piccolo, semplice e pulito. Non tutti i piccoli zuccheri sintattici valgono la pena. – soc

+7

Non sono convinto che Scala sia piccolo e semplice. Rispetto a qualcosa come lua, comunque ... –

+9

Confronto con Python Scala non sembra così piccolo e semplice, ha molti più costrutti di Python. –

risposta

20
scala> import collection.IterableLike 
import collection.IterableLike 

scala> implicit def pythonicSlice[A, Repr](coll: IterableLike[A, Repr]) = new { 
    | def apply(subrange: (Int, Int)): Repr = coll.slice(subrange._1, subrange._2) 
    | } 
pythonicSlice: [A,Repr](coll: scala.collection.IterableLike[A,Repr])java.lang.Object{def apply(subrange: (Int, Int)): Repr} 

scala> val list = List(3, 4, 11, 78, 3, 9) 
list: List[Int] = List(3, 4, 11, 78, 3, 9) 

scala> list(2 -> 5) 
res4: List[Int] = List(11, 78, 3) 

Questo farà?

Disclaimer: Non correttamente generalizzato.


EDIT:

scala> case class PRange(start: Int, end: Int, step: Int = 1) 
defined class PRange 

scala> implicit def intWithTildyArrow(i: Int) = new { 
    | def ~>(j: Int) = PRange(i, j) 
    | } 
intWithTildyArrow: (i: Int)java.lang.Object{def ~>(j: Int): PRange} 

scala> implicit def prangeWithTildyArrow(p: PRange) = new { 
    | def ~>(step: Int) = p.copy(step = step) 
    | } 
prangeWithTildyArrow: (p: PRange)java.lang.Object{def ~>(step: Int): PRange} 

scala> implicit def pSlice[A](coll: List[A]) = new { 
    | def apply(prange: PRange) = { 
    |  import prange._ 
    |  coll.slice(start, end).grouped(step).toList.map(_.head) 
    | } 
    | } 
pSlice: [A](coll: List[A])java.lang.Object{def apply(prange: PRange): List[A]} 

scala> val xs = List.range(1, 10) 
xs: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> xs(3 ~> 9) 
res32: List[Int] = List(4, 5, 6, 7, 8, 9) 

scala> xs(3 ~> 9 ~> 2) 
res33: List[Int] = List(4, 6, 8) 
+0

gr8.puoi modificarlo in modo negativo e anche i passaggi? – Emil

+0

quale scala stai usando? Sto usando 2.7. Dice "IterableLike" non è un membro della collezione. – Emil

+0

, per favore, spiega il codice. Sono nuovo di scala. – Emil

7

Vedi l'ScalaAPI here

Quindi non

la stessa convenienza di notazione, ma l'operazione è lì

fetta def (da: Int, fino a quando: Int) : Seq [A]

Seleziona un intervallo di elementi.

Seleziona un intervallo di elementi.

Nota: c.slice (da, a) è equivalente a (ma forse più efficiente rispetto) c.drop (da) .Take (a - da)

dall'indice del primo restituito elemento in questa sequenza. fino a l'indice uno dopo l'ultimo elemento restituito in questa sequenza.

rendimenti

una sequenza contenente gli elementi da indice da e si estendono fino a (esclusi) indice finché di questa sequenza.

classi di definizione: IterableLike → TraversableLike

48

metodo equivalente a Scala (con una sintassi leggermente diversa) esiste per tutti i tipi di sequenze:

scala> "Hello world" slice(0,4) 
res0: String = Hell 

scala> (1 to 10) slice(3,5) 
res1: scala.collection.immutable.Range = Range(4, 5) 

La più grande differenza rispetto ai affettare in Python è che gli indici di inizio e di fine sono obbligatori in Scala.

+0

è sovraccarico dell'operatore possibile utilizzarlo come la sintassi python. Penso che sia più elegante. – Emil

+4

Scala non ha operatori. – soc

2

Si noti che questo funziona non proprio utilizzando apply, ma generalizza alle liste, stringhe, array, ecc:

implicit def it2sl[Repr <% scala.collection.IterableLike[_, Repr]](cc: Repr) = new { 
    def ~>(i : Int, j : Int) : Repr = cc.slice(i,j) 
} 

L'utilizzo è:

scala> "Hello World" ~> (3, 5) 
res1: java.lang.String = lo 

scala> List(1, 2, 3, 4) ~> (0, 2) 
res2: List[Int] = List(1, 2) 

scala> Array('a', 'b', 'c', 'd') ~> (1, 3) 
res3: Array[Char] = Array(b, c) 

Si potrebbe voler rinominare il metodo con qualcos'altro che ti piace.Tranneapply (perché c'è già una conversione da String a StringLike che decora String con un metodo apply - analogamente, con ArrayOps - e v'è già un metodo applicare su altri tipi di raccolta come List).

Grazie per Daniel per il suggerimento di utilizzare una vista vincolata.