Выход Iterable.sliding в качестве кортежа

Метод скользящий в коллекциях возвращает скользящее окно заданного размера в форме X[Iterable[A]], где X - тип коллекции, а A - тип элемента. Часто мне нужны два или три элемента, и я предпочитаю их назвать. Один уродливый обходной путь для sliding(2) следующий:

points.sliding(2).foreach{ twoPoints =>
      val (p1,p2) = (twoPoints.head,twoPoints.last)
      //do something
}

Это отстой и работает только для двух элементов. Также обратите внимание, что

(a,b) = (twoPoints(0),twoPoints(1))

не работает.

Ответ 1

Я сделал это в этом только на прошлой неделе.

points.sliding(2).foreach { case X(p1, p2) => ... }

Если points является Array, замените X на Array. Если это List, замените X на List и т.д.

Обратите внимание, что вы выполняете сопоставление с шаблоном, поэтому для параметра необходимо {} вместо ().

Ответ 2

twoPoints будет представлять собой список. Попробуйте следующее:

points.sliding(3).foreach{ _ match {
  case Seq(a, b, c) => {
      //do something
  }
}

Вы будете удивлены, какие виды привязки кунгофа позволяют вам уйти.

Ответ 3

Недавно мне захотелось немного больше сахара в моих раздвижных итераторах, поэтому я придумал это:

implicit class SlidingOps[A](s: Seq[A]) {
  def slidingPairs = (s, s.tail).zipped
  def slidingTriples = (s, s.tail, s.tail.tail).zipped
}

Это работает с любым Seq, но, вероятно, наиболее эффективно с List. .zipped возвращает scala.runtime.Tuple2Zipped (или Tuple3Zipped для 3-элементного кортежа), который определяет несколько знакомых методов более высокого порядка, поэтому их аргументы принимают несколько аргументов, поэтому вы можете написать:

points.slidingPairs.foreach { (a, b) => ... }

или даже:

(1 to 10).slidingTriples.map(_ + _ + _)

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