Scala 中的切片符号?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3932582/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:30:24  来源:igfitidea点击:

Slice notation in Scala?

pythonscalaslice

提问by Emil

Is there something similar to the slice notation in Pythonin Scala?

在 Scala 中是否有类似于Python的切片符号的东西?

I think this is really a useful operation that should be incorporated in all languages.

我认为这确实是一个有用的操作,应该被纳入所有语言。

采纳答案by missingfaktor

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)

Will this do?

这会吗?

Disclaimer: Not properly generalized.

免责声明:没有正确概括。



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)

回答by Vasil Remeniuk

Equivalent method in Scala (with a slightly different syntax) exists for all kinds of sequences:

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)

The biggest difference compared to slicing in Python is that start and end indices are mandatory in Scala.

与 Python 中的切片相比,最大的不同在于 Scala 中的开始和结束索引是强制性的。

回答by The Archetypal Paul

See the ScalaAPI here

此处查看ScalaAPI

So not the same notational convenience, but the operation is there

所以不一样的符号方便,但操作是有的

def slice (from: Int, until: Int) : Seq[A]

Selects an interval of elements.

Selects an interval of elements.

Note: c.slice(from, to) is equivalent to (but possibly more efficient than) c.drop(from).take(to - from)

from the index of the first returned element in this sequence. until the index one past the last returned element in this sequence.

returns

a sequence containing the elements starting at index from and extending up to (but not including) index until of this sequence.

definition classes: IterableLike → TraversableLike

def slice (from: Int, until: Int) : Seq[A]

选择元素的间隔。

选择元素的间隔。

注意:c.slice(from, to) 等价于(但可能比)c.drop(from).take(to - from)

从此序列中第一个返回元素的索引开始。直到索引超过此序列中最后一个返回的元素。

回报

一个包含从 index from 开始并延伸到(但不包括)index直到该序列的元素的序列。

定义类:IterableLike → TraversableLike

回答by oxbow_lakes

Note that this does not quite work by using apply, but it generalizesto lists, strings, arrays, etc:

请注意,这并不能通过 using 完全起作用apply,但它可以推广到列表、字符串、数组等:

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

The usage is:

用法是:

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)

You might want to rename the method to something else that takes your fancy. Exceptapply(because there is already a conversion from Stringto StringLikewhich decorates String with an applymethod - similarly with ArrayOps- and there is already an apply method on other collection types such as List).

您可能想将该方法重命名为您喜欢的其他名称。除了apply(因为已经有一个从Stringto的转换,StringLike它用一个apply方法装饰字符串- 与ArrayOps-类似- 并且在其他集合类型上已经有一个 apply 方法,例如List)。

Thanks for Danielfor the hint to use a view bound.

感谢Daniel提示使用视图边界。