2010-10-14 21 views
29

Existe-t-il quelque chose de similaire à the slice notation in Python sur Scala?Notation de tranche dans Scala?

Je pense que c'est vraiment une opération utile qui devrait être incorporée dans toutes les langues.

+2

Eh bien, certaines personnes préfèrent une langue qui reste petite, simple et propre. Pas tous les petits sucres syntaxiques valent la peine. – soc

+7

Je ne suis pas convaincu que Scala est petit et simple cependant. Comparé à quelque chose comme lua, de toute façon ... –

+9

Comparer à Python Scala n'a pas l'air si petit et simple, il a beaucoup plus de constructions que Python. –

Répondre

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) 

Est-ce que cela va?

Clause de non-responsabilité: Pas généralisé.


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.can vous le modifiez pour prendre le négatif et les étapes aussi? – Emil

+0

quel scala utilisez-vous? J'utilise 2.7.Il dit 'IterableLike' n'est pas un membre de la collection. – Emil

+0

aussi s'il vous plaît expliquer le code.je suis nouveau à scala. – Emil

7

Voir la ScalaAPI here

donc pas le même confort notationnelle, mais l'opération est là

tranche def (à partir de: Int, jusqu'à ce que: Int) : Seq [A]

Sélectionne un intervalle d'éléments.

Sélectionne un intervalle d'éléments.

Note: c.slice (de, à) est équivalent à (mais peut-être plus efficace que) c.drop (de) .take (à - de)

de l'indice du premier retour élément dans cette séquence. jusqu'à l'index passé le dernier élément retourné dans cette séquence.

rendements

une séquence contenant les éléments à partir de l'index de et étendant jusqu'à index (mais non compris) jusqu'à ce que de cette séquence.

classes de définition: IterableLike → TraversableLike

48

méthode équivalente à Scala (avec une syntaxe légèrement différente) existe pour toutes sortes de séquences:

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 plus grande différence par rapport à trancher en Python est-ce que les indices de début et de fin sont obligatoires dans Scala.

+0

est la surcharge de l'opérateur possible de l'utiliser comme syntaxe python.Je pense que c'est plus élégant. – Emil

+4

Scala n'a aucun opérateur. – soc

2

Notez que cela ne fonctionne pas tout à fait à l'aide apply, mais il généralise à des listes, des chaînes, des tableaux, etc.:

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

L'utilisation est:

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) 

Vous voudrez peut-être renommer la méthode en autre chose qui vous intéresse.Saufapply (parce qu'il ya déjà une conversion String-StringLike qui décore cordes avec une méthode apply - De même avec ArrayOps - et il existe déjà une méthode apply sur d'autres types de collections tels que List).

Merci pour Daniel pour l'indice d'utiliser une vue liée.