2010-10-14 395 views
29

在Scala中是否有類似the slice notation in Python的東西?Scala中的切片符號?

我認爲這是一個非常有用的操作,應該被合併到所有語言中。

+2

那麼,有些人更喜歡保持小,簡單和乾淨的語言。不是每一個小小的語法糖都是值得的。 – soc 2010-10-14 11:59:19

+7

雖然我不相信Scala很小很簡單。與lua等相比,無論如何... – 2010-10-14 13:35:13

+9

與Python相比,Scala看起來並不那麼簡單,它具有比Python更多的構造。 – 2012-05-31 09:07:18

回答

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) 

請問這樣做?

聲明:未正確推廣。


編輯:

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。你可以修改它以採取負面和步驟也? – Emil 2010-10-14 11:52:30

+0

你正在使用哪個scala?我使用2.7。它說'IterableLike'不是集合的成員。 – Emil 2010-10-14 11:55:42

+0

也請解釋code.i'm新的斯卡拉。 – Emil 2010-10-14 11:57:53

7

參見ScalaAPI here

所以不一樣的符號上的便利,但操作有

DEF切片(來自:中等,直到:智力) :序號[A]

選擇元素的間隔。

選擇元素的間隔。

注:c.slice(從,到)等效 (但可能比更有效) c.drop(從)。取(以 - 從)從所述第一返回的索引

元素在這個序列中。直到 索引1通過此序列中最後一個返回的元素。

返回

含有從開始於索引和延伸 直到(但不包括)索引,直至該序列的 的元素的序列。

定義類:IterableLike→ TraversableLike

48

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中,起始和結束索引是強制性的。

+0

是重載操作符的可能使用它像Python語法。我認爲這是更優雅。 – Emil 2010-10-14 11:33:37

+4

Scala沒有運營商。 – soc 2010-10-14 12:09:10

2

注意,這完全不是那麼回事使用apply,但它概括清單,字符串,數組等:

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

用法是:

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) 

您可能希望將該方法重命名爲其他您需要的東西。apply(因爲已經有從StringStringLike轉換其裝飾字符串以apply方法 - 與ArrayOps類似 - 和已經存在於其他集合類型如List的應用方法)。

感謝丹尼爾爲提示使用視圖綁定。