我有一个不可变的数据结构,我在 Maps 中嵌套了值,如下所示:
case class TradingDay(syms: Map[String, SymDay] = Map.empty)
case class SymDay(sym: String, traders: Map[String, TraderSymDay] = Map.empty)
case class TraderSymDay(trader: String, sym: String, trades: List[Trade] = Nil)
另外,我有一个当天所有交易的列表,我想生成
TradingDay
结构,其中case class Trade(sym: String, trader: String, qty: Int)
我试图弄清楚如何通过折叠我的交易来使用镜头更新这个结构(见附录):
(TradingDay() /: trades) { (trd, d) =>
def sym = trd.sym
def trader = trd.trader
import TradingDay._
import SymDay._
import TraderSymDay._
val mod =
for {
_ <- (Syms member sym).mods(
_ orElse some(SymDay(sym)))
_ <- (Syms at sym andThen Traders member trader).mods(
_ orElse some(TraderSymDay(trader, sym)))
_ <- (Syms at sym andThen (Traders at trader) andThen Trades).mods(
trd :: _)
x <- init
} yield x
mod ! d
}
这有效;但我想知道我是否可以减少重复(在添加到 map 然后修改 map 键处的值方面。它似乎并不比相关的深层复制更烦人。
附录 - 镜片
object TradingDay {
val Syms = Lens[TradingDay, Map[String, SymDay]](_.syms, (d, s) => d.copy(syms = s))
}
object SymDay {
val Traders = Lens[SymDay, Map[String, TraderSymDay]](_.traders, (d, t) => d.copy(traders = t))
}
object TraderSymDay {
val Trades = Lens[TraderSymDay, List[Trade]](_.trades, (d, f) => d.copy(trades = f))
}
最佳答案
和
type @>[A,B] = Lens[A, B]
并通过保持这个镜头
val Syms : Lens[TradingDay, Map[String, SymDay]]
并定义这些镜头:
val F : Map[String, SymDay] @> Option[SymDay] = ...
val G : Option[SymDay] @> Map[String, TraderSymDay] = ...
val H : Map[String, TraderSymDay] @> Option[TraderSymDay] = ...
val I : Option[TraderSymDay] @> List[Trade] = ...
val J: TradingDay @> List[Trade] = Syms >=> F >=> G >=> H >=> I
你可以得到这个:
(trades /: TradingDay()){ (trd, d) => (J.map(trd :: _).flatMap(_ => init)) ! d }
关于scala - 在深度复制到 Map 值时避免重复使用镜头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10245904/