Манипулирование SortedMap с использованием foldleft
У меня есть код, который преобразует следующие типы данных:
от: SortedMap[Long, SortedMap[String, Double]] до: SortedMap[String, Array[Double]]
Может кто-нибудь объяснить, как этот код выполняет вышеуказанные манипуляции?
val convertedDataWindow = dataWindow.values.foldLeft(SortedMap.empty[String, Array[Double]]) {
case (res0, map) =>
(res0 /: map) {
case (res1, (key, value)) =>
res1.updated(key, res1.getOrElse(key, Array.empty) :+ value)
}
}
1 ответ
Сначала рассмотрим внутреннюю функцию:
def something(res0: SortedMap[String, Array[Double]],
map: SortedMap[String, Double]) = (res0 /: map) {
case (res1, (key, value)) =>
res1.updated(key, res1.getOrElse(key, Array.empty) :+ value)
}
/:
это другое имя для foldLeft
, это так же, как
map.foldLeft(res0) { ...}
Ты знаешь как foldLeft
работает вообще? Он проходит через коллекцию, используя данную функцию для "слияния" каждого значения в начальное значение по очереди. Итак, это начинается с res0
и для каждого (key, value)
в map
, мы объединяем его в наш рабочий результат, используя .updated
: добавляем новую запись на карту, с ключом key
и значение res1.getOrElse(key, Array.empty) :+ value
, То есть, если для этого ключа уже есть запись, мы добавим value
на конец этого; в противном случае мы делаем новый Array
содержащий только value
,
Таким образом, объединяя все это, эта функция объединяется map
в res0
путем создания новых записей для любых новых ключей или помещения значений в Array
для любых существующих ключей.
Теперь полная функция делает другое foldLeft
; мы могли бы написать это как:
dataWindow.values.foldLeft(SortedMap.empty)(something)
Итак, что это делает, начиная с пустой карты, а затем для каждого из dataWindow.values
в свою очередь, объединяя это в нашу рабочую карту.
(Конечно, когда я говорю о "слиянии", в действительности все является неизменным, и мы создаем новую "рабочую" карту каждый раз, когда мы проходим цикл. Но иногда яснее представить одну изменяемую "рабочую" карту res
)