Выход 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(_ + _ + _)
Вы можете оптимизировать реализацию дальше, если хотите, чтобы она была действительно эффективной для типов без списка.