Scala中的切片 notation?
在Scala中,有没有类似于Python中的切片表示法的东西呢?
我觉得这个操作真的很有用,应该在所有编程语言中都有。
4 个回答
9
可以在这里查看 Scala的API
虽然表示方式不太一样,但这个操作是可以做到的。
定义一个叫做 slice 的方法,它需要两个参数:from(开始的索引)和 until(结束的索引),返回一个序列 Seq[A]。
这个方法的作用是选择一段元素。
注意:c.slice(from, to) 的效果和 c.drop(from).take(to - from) 是一样的,但可能效率更高。
这里的 from 是指返回的元素在这个序列中的第一个索引,until 是指在这个序列中最后一个返回元素的下一个索引。
这个方法返回的是一个序列,包含从索引 from 开始,到索引 until 之前的所有元素。
定义的类:IterableLike → TraversableLike
55
在Scala中,有一种等效的方法(语法稍微不同)适用于所有类型的序列:
scala> "Hello world" slice(0,4)
res0: String = Hell
scala> (1 to 10) slice(3,5)
res1: scala.collection.immutable.Range = Range(4, 5)
与Python中的切片相比,Scala的一个最大不同是,开始和结束的索引是必须提供的。
21
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)
这样可以吗?
免责声明:这个内容没有经过全面的概括。
编辑:
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)