我猜这个问题可以重新定义如下。
- 按关键字后缀对给定映射中的键值对进行分组。
- 为每个分组创建地图并将它们倒入一个新的向量中。
如果这些假设是正确的,这就是我的解决方案。
首先,定义一个辅助函数,称为kv->skv,它将原始键值对 ([k v]) 转换为后缀向量和修改后的键值对 ([suffix [k' v])。
user> (def items {:item_name_1 "Great Deal"
:item_options_2 "blah: 2"
:item_name_2 "Awesome Deal"
:item_options_1 "foo: 3"
:item_quantity_1 "1"
:item_price_2 "9.99"
:item_price_1 "9.99"
:itemCount "2"})
#'user/items
user> (defn- kv->skv
[[k v]]
(let [[_ k' s] (re-find #"(.+)_(\d+)" (name k))]
[s [k' v]]))
#'user/kv->skv
user> (def items' (map kv->skv items))
#'user/items'
user> (clojure.pprint/pprint items')
(["1" ["item_name" "Great Deal"]]
["2" ["item_options" "blah: 2"]]
["2" ["item_name" "Awesome Deal"]]
["1" ["item_options" "foo: 3"]]
["1" ["item_quantity" "1"]]
["2" ["item_price" "9.99"]]
["1" ["item_price" "9.99"]]
[nil [nil "2"]])
nil
然后,使用项目键过滤项目。
user> (def item-keys #{:item_name :item_options :item_price :item_quantity})
#'user/item-keys
user> (def items-filtered (filter (comp item-keys keyword first second) items'))
#'user/items-filtered
user> (clojure.pprint/pprint items-filtered)
(["1" ["item_name" "Great Deal"]]
["2" ["item_options" "blah: 2"]]
["2" ["item_name" "Awesome Deal"]]
["1" ["item_options" "foo: 3"]]
["1" ["item_quantity" "1"]]
["2" ["item_price" "9.99"]]
["1" ["item_price" "9.99"]])
nil
其次,使用group-by函数按后缀对修改后的键值对进行分组。
user> (def groupings (group-by first items-filtered))
#'user/groupings
user> (clojure.pprint/pprint groupings)
{"1"
[["1" ["item_name" "Great Deal"]]
["1" ["item_options" "foo: 3"]]
["1" ["item_quantity" "1"]]
["1" ["item_price" "9.99"]]],
"2"
[["2" ["item_options" "blah: 2"]]
["2" ["item_name" "Awesome Deal"]]
["2" ["item_price" "9.99"]]]}
nil
并将分组转换为地图。
user> (def what-you-want (->> (vals groupings)
(map #(->> %
(map second)
(into {})))))
#'user/what-you-want
user> (clojure.pprint/pprint what-you-want)
({"item_name" "Great Deal",
"item_options" "foo: 3",
"item_quantity" "1",
"item_price" "9.99"}
{"item_options" "blah: 2",
"item_name" "Awesome Deal",
"item_price" "9.99"})
nil
最后,将这些步骤整合到一个函数中。
(defn extract-items
[items item-keys]
(let [kv->skv (fn
[[k v]]
(let [[_ k' s] (re-find #"(.+)_(\d+)" (name k))]
[s [k' v]]))]
(->> items
(map kv->skv)
(filter (comp item-keys keyword first second))
(group-by first)
vals
(map #(->> %
(map second)
(into {}))))))
有效。
user> (clojure.pprint/pprint (extract-items items item-keys))
({"item_name" "Great Deal",
"item_options" "foo: 3",
"item_quantity" "1",
"item_price" "9.99"}
{"item_options" "blah: 2",
"item_name" "Awesome Deal",
"item_price" "9.99"})
nil
希望这个循序渐进的方法对您有所帮助。