Срез записи в Scala? - PullRequest
       6

Срез записи в Scala?

29 голосов
/ 14 октября 2010

Есть ли что-то похожее на обозначение среза в Python в Scala?

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

Ответы [ 4 ]

50 голосов
/ 14 октября 2010

Эквивалентный метод в 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.

20 голосов
/ 14 октября 2010
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)
8 голосов
/ 14 октября 2010

См. ScalaAPI здесь

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

def slice (от: Int, до: Int): Seq [A]

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

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

Примечание: c.slice (from, to) эквивалентно (но, возможно, более эффективно, чем) c.drop (from) .take (to-from)

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

возвращает

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

определение классов: IterableLike → TraversableLike

2 голосов
/ 15 октября 2010

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

Спасибо за Даниэль за подсказку использовать границы вида.

...