更改数据格式:
- 将每个日期的数据向量合并到一个地图中
.
- 将整个事物制作成一张地图,以日期关键字为关键字。
- 丢失
:meat-weight-balance 数据 - 这是多余的。
(前两个更改遵循@leetwinski's advice)
我们得到...
(def data
{:2007-08-05 {:meat-weight-gain 100, :meat-weight-loss 80},
:2007-08-06 {:meat-weight-gain 10, :meat-weight-loss 60},
:2007-08-07 {:meat-weight-gain 40, :meat-weight-loss 80},
:2007-08-08 {:meat-weight-gain 100, :meat-weight-loss 0}})
这些条目恰好按日期顺序排列,因为它是一张小地图。如果我们想确保日期顺序,我们最好有一个排序的地图:
(def sorted-data (into (sorted-map) data))
这看起来并没有什么不同,但总是会按关键顺序显示数据,这是 - 谢天谢地 - 日期顺序。
这似乎是一个很长的路要走,以使记录在向量中的原始顺序,但向量有未使用的日期关键字顺序穿过它:Don't R 重复Y我们自己。
让我们计算一下每日余额:
(def balances
(map-vals #(- (:meat-weight-gain %) (:meat-weight-loss %)) sorted-data))
balances
=> {:2007-08-05 20, :2007-08-06 -50, :2007-08-07 -40, :2007-08-08 100}
...其中map-vals 函数是map 和mapv 的类似物,适用于地图的值:
(defn map-vals [f m]
(into (empty m) (map (fn [[k v]] [k (f v)])) m))
请注意,它返回的地图种类与给定的地图种类相同,在本例中是已排序的地图。
我们想知道在哪些时期出现了净体重减轻。目前尚不清楚这意味着什么。让我们看看从一开始的净重增加:
(reductions (fn [[_ av] [k v]] [k (+ av v)]) balances)
=> ([:2007-08-05 20] [:2007-08-06 -30] [:2007-08-07 -70] [:2007-08-08 30])
或者我们可以将序列划分为获得和损失部分:
(partition-by (fn [[_ v]] (neg? v)) balances)
=> (([:2007-08-05 20]) ([:2007-08-06 -50] [:2007-08-07 -40]) ([:2007-08-08 100]))
我们需要partition-by 的一个变体,它通过判别函数的值作为其子序列的键,就像group-by 所做的那样。然后你就知道什么是获利范围,什么是亏损范围。一个便宜又开朗的版本是......
(defn group-partition-by [f coll]
(let [parts (partition-by f coll)]
(map #(-> % first f (list %)) parts)))
然后
(group-partition-by (fn [[_ v]] (neg? v)) balances)
=> ((false ([:2007-08-05 20]))
(true ([:2007-08-06 -50] [:2007-08-07 -40]))
(false ([:2007-08-08 100])))
您可能希望将此数据减少为从日期范围到总余额的(排序的)映射。
转化
我们如何从given 到data?我们可以通过如下方式直接到达sorted-data:
(def sorted-data
(->> given
(into (sorted-map))
(map-vals (comp #(into {} %) #(remove :meat-balance %)))))
sorted-data
=>
{:2007-08-05 {:meat-weight-gain 100, :meat-weight-loss 80},
:2007-08-06 {:meat-weight-gain 10, :meat-weight-loss 60},
:2007-08-07 {:meat-weight-gain 40, :meat-weight-loss 80},
:2007-08-08 {:meat-weight-gain 100, :meat-weight-loss 0}}
展示次数
注意
您最好使用欧洲日期,而不是美国日期,否则您将需要更聪明的keyfn 来按日期顺序获取记录。我更喜欢 clj-time local-dates 而不是关键字作为键
- 如果代码跨越大西洋;
- 以便您可以运行有效性检查,例如您有记录
每天。