У меня есть список объектов в последовательности val as = Seq[A]
. A
выглядит так:
import java.time.Instant
case class A(t: String, start: Instant, end: Instant)
Теперь я хочу объединить элемент в as
условно: всякий раз, когда два последующих, то есть непосредственно смежных, элементы a1
и a2
имеют одинаковое значение для t
, они должны быть объединены в одно, как это:
object A {
def merge(a1: A, a2: A): A = {
require(a1.t == a2.t)
A(a1.t, a1.start, a2.end)
}
}
Обратите внимание, что элементы, которые непосредственно не преуспевают в другом, никогда не должны объединяться, например ::
Seq(A("a", ...), A("a", ...), A("b", ...), ...) // -> merge the first two elements
Тем не менее:
Seq(A("a", ...), A("b", ...), A("a", ...), ...) // -> do not merge any elements
Существует аналогичный вопрос для SO , но он объединяет несколько списков, поэтому он не применим к моему случаю.
Мой первый подход:
as.zip(as.tail)
.map {
case (a1: A, a2: A) if (a1.t == a2.t) => merge(a1, a2)
case (a1: A, a2: A) => ???
}
Хотя есть несколько недостатков. Кроме того, я не уверен, что делать во втором случае (то есть оставить a1
и a2
как есть), это также не работает для более чем одного последующего элемента, который должен быть объединен.
Моя интуиция ведет меня больше к foldLeft
:
as.foldLeft(???)(A.merge)
Это решает проблему с несколькими последующими элементами, которые необходимо объединить. Однако он попытается объединить все элементы, что невозможно с моей реализацией merge
.
Я мог бы адаптировать merge()
, но мне остается неясным, как: если a1.t == a2.t
, тип результата должен быть новым A
, тогда как в противном случае он должен "возвращать" a1
и a2
, поскольку они были.
Мой подход к последней идее заключался в добавлении этих методов в класс A
:
def merge(that: A): (A, Option[A]) =
if (this.t == that.t)
(A(t, this.start, that.end), None)
else
(this, Some(that))
Но здесь я не могу реально использовать вывод merge()
в foldLeft()
вызове последовательности as
.
Основная проблема заключается в любом подходе: как мне справиться с тем фактом, что иногда (при совпадении t
) я хочу добавить один новый A
к новой последовательности, тогда как в других случаях мне нужно добавить два элемента.
Я немного растерялся, как решить эту проблему функциональным программированием.
Конечно, я мог бы перебрать список as
, сохранить те, которые должны быть объединены в новую структуру данных, и сгенерировать их снова. Есть ли лучший способ?