2010-10-14 2 views
29

Есть ли что-то похожее на the slice notation in Python в Scala?Обозначение фрагмента в Scala?

Я думаю, что это действительно полезная операция, которая должна быть включена во все языки.

+2

Ну, некоторые люди предпочитают язык, который остается маленьким, простым и чистым. Не каждый маленький синтаксический сахар стоит того. – soc

+7

Я не уверен, что Скала маленькая и простая. По сравнению с чем-то вроде lua, так или иначе ... –

+9

По сравнению с Python Scala выглядит не так маловажно и просто, у него гораздо больше конструкций, чем у Python. –

ответ

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) 

Будет ли это делать?

Отказ от ответственности: Не правильно обобщены.


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 вы можете изменить его, чтобы принять отрицательный результат и шаги также? – Emil

+0

которые вы используете? Я использую 2.7.It сказать, что «IterableLike» не входит в коллекцию. – Emil

+0

также объясните пожалуйста код.i'm новый для scala. – Emil

7

См ScalaAPI here

Так не же удобства записи, но операция не существует

Защиту срез (от: Int до: Int) : Seq [A]

Выбирает интервал элементов.

Выбирает интервал элементов.

Примечание: c.slice (от, до) эквивалентно (но, возможно, более эффективным, чем) c.drop (с) .Снять (к - от)

из индекса первого возвращаемого элемент в этой последовательности. до индекс один за последним возвращенным элементом в этой последовательности.

возвращает

последовательности, содержащая элементы, начиная с индексом от и простирающихся до (но не включая) до индекса этой последовательности.

классов определений: 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

+4

У Scala нет операторов. – soc

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 (потому что есть уже переход от String к StringLike, которые украсят строку с apply методом - аналогично с ArrayOps - и уже есть способ применить на других типах коллекций, таких как List).

Thanks for Daniel для получения подсказку.