У меня есть следующие входные значения
import java.sql.Timestamp
import java.lang.{Double => JDouble}
val date = Timestamp.valueOf("2021-08-01 00:00:00")
val contractRate: Map[String, JDouble] = Map("ITABUS" -> 0.075,
"KARAT-S" -> 0.10,
"KAUTRA" -> 0.05)
val timeBoundContractRatesList: Map[String, List[(Timestamp, JDouble)]] = Map(
"ITABUS" -> List((Timestamp.valueOf("2021-07-30 23:59:59"), 0.085.asInstanceOf[JDouble]),
)
)
Мое требование здесь:
Есть 2 вида ставок. Одна фиксированная ставка, а другая привязанная к времени ставка
Мне нужно применить скорость с привязкой ко времени, если дата больше, чем сегодня (например)
Я пытаюсь использовать подход, чтобы иметь единую консолидированную карту, как показано ниже.
val withTimeBoundContractRate = contractRate ++ timeBoundContractRatesList
.map { case (carrier, timeRateSet) =>
val filteredEntry = timeRateSet
.filter { case (startDate, _) => date.after(startDate) }
(carrier, filteredEntry.map(_._2).headOption)
}
.filter(_._2.nonEmpty)
Проблема с выводом. Я получаю вывод ниже
withTimeBoundContractRate: scala.collection.immutable.Map[String,java.io.Serializable] = Map(ITABUS -> Some(0.085), KARAT-S -> 0.1, KAUTRA -> 0.05)
Но я ищу карту с исходным типом данных (без опции)
withTimeBoundContractRate: Map[String, JDouble] = Map(ITABUS -> 0.085, KARAT-S -> 0.1, KAUTRA -> 0.05)
Или есть совершенно другой подход для эффективного решения этой проблемы?
Как правило, лучше использовать типы Scala и преобразовывать их в типы Java на пути входа/выхода из кода Java, чем использовать типы Java в коде Scala.
Вы можете использовать align
из кошки, чтобы объединить обе карты.
(Думаю, я неправильно понял, что вы пытаетесь сделать изначально, поэтому я удалил первый ответ, чтобы заменить его этим):
На самом деле у вас почти есть это, единственная проблема в том, что значения на вашей второй карте Options
. Просто «разверните» их:
contractRate ++ timeBoundContractRatesList.mapValues {
_.find(date.after(_._1)).map(_._2)
}.collect { case(k, Some(v)) => k -> v }
Основное отличие от вашего фрагмента здесь заключается в использовании collect
вместо filter
: он позволяет не только удалять пустые значения, но и преобразовывать непустые, чтобы избавиться от Option
вокруг них.
Как я вижу, вы отфильтровали непустые значения в конце операции с картой, поэтому вы можете либо сделать:
.map(tuple => (tuple._1, tuple._2.get)) // since you're sure that it is not empty
, либо использовать метод сбора вместо фильтрации непустых, а затем использовать метод .get:.collect { case (startDate, Some(otherValue) => startDate -> otherValue } // uses one iteration instead of 2 iterations.