2010-10-14 19 views
29

¿Hay algo similar a the slice notation in Python en Scala?Notación de división en Scala?

Creo que esta es una operación realmente útil que debe incorporarse en todos los idiomas.

+2

Bueno, algunas personas prefieren un lenguaje que se mantenga pequeño, simple y limpio. No todo el azúcar sintáctico poco vale la pena. – soc

+7

No estoy convencido de que Scala sea pequeño y simple. Comparado con algo como lua, de todos modos ... –

+9

Comparando con Python Scala no se ve tan pequeño y simple, tiene muchos más constructos que Python. –

Respuesta

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) 

¿Esto esto?

Descargo de responsabilidad: No generalizada correctamente.


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.¿puedes modificarlo para que tome negativo y también pasos? – Emil

+0

¿Qué scala estás usando? Estoy usando 2.7. Dijo que 'IterableLike' no es miembro de la colección. – Emil

+0

también explique el código. Soy nuevo en Scala. – Emil

7

Véase el ScalaAPI here

Así que no

la misma conveniencia de notación, pero la operación es no

rebanada def (a partir de: Int, hasta que: Int) : SEQ [A]

Selecciona un intervalo de elementos.

Selecciona un intervalo de elementos.

Nota: c.slice (de, a) es equivalente a (pero posiblemente más eficiente que) c.drop (de) .take (a - a)

del índice del primer devuelto elemento en esta secuencia. hasta el índice uno más allá del último elemento devuelto en esta secuencia.

rendimientos

una secuencia que contiene los elementos a partir de índice a partir de y se extienden hasta (pero no incluyendo) índice hasta de esta secuencia.

clases de definición de: IterableLike → TraversableLike

48

existe Método equivalente en Scala (con una sintaxis ligeramente diferente) para todos los tipos de secuencias:

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 diferencia más grande en comparación con rebanar en Python es que los índices de inicio y final son obligatorios en Scala.

+0

está sobrecargando la capacidad del operador para usarlo como la sintaxis de python. Creo que es más elegante. – Emil

+4

Scala no tiene operadores. – soc

2

Tenga en cuenta que esto hace el trabajo no es mediante el uso de apply, pero generaliza a listas, cadenas, matrices, etc:

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

El uso es:

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) 

Es posible que desee cambiar el nombre del método a otra cosa que le apetezca.Exceptoapply (porque ya hay una conversión String-StringLike que decora la secuencia con un método apply - de manera similar con ArrayOps - y ya es un método de aplicación en otros tipos de recolección tales como List).

Gracias por Daniel por la sugerencia de utilizar una vista encuadernada.