Vector 基于密钥将向量拆分为向量向量
我有一个单独的对象向量,我想将其转换为对象向量向量,其中子向量中的每个对象对于特定成员具有相同的值。e、 gVector 基于密钥将向量拆分为向量向量,vector,clojure,functional-programming,lisp,Vector,Clojure,Functional Programming,Lisp,我有一个单独的对象向量,我想将其转换为对象向量向量,其中子向量中的每个对象对于特定成员具有相同的值。e、 g [{:sku "105"}, {:sku "105"}, {:sku "120"}] 变成 [[{:sku "105"}, {:sku "105"}], [{:sku "120"}]] 我试图掌握函数式的思维方式,但我很确定我还没有掌握,因为我的代码看起来相当笨拙。但到目前为止,我得到的是: (defn separate-by-invoice [original-invoices]
[{:sku "105"}, {:sku "105"}, {:sku "120"}]
变成
[[{:sku "105"}, {:sku "105"}], [{:sku "120"}]]
我试图掌握函数式的思维方式,但我很确定我还没有掌握,因为我的代码看起来相当笨拙。但到目前为止,我得到的是:
(defn separate-by-invoice [original-invoices]
(let [sorted-invoices (sort-by :invoice-number original-invoices)]
(def temp-invoices [])
(reduce (fn [final-invoices invoice]
(let [prev-invoice-number (get-in (last temp-invoices) [:invoice-number])
invoice-number (get-in invoice [:invoice-number])]
(if (= prev-invoice-number invoice-number)
(do
(into temp-invoices invoice))
(do
(into final-invoices temp-invoices)
(def temp-invoices [])
(into temp-invoices invoice))))
final-invoices)
[]
sorted-invoices)))
基本上,我的想法是,我形成一个向量,temp invoices,用相同发票号的所有条目填充它,然后一旦我们得到所有条目,将该向量插入最终向量,并返回该值。但最终发票似乎总是一个空向量。我做错了什么?clojure通常是如何做到这一点的?让我们将其分为两个子问题:
user> (def x [{:sku "105"}, {:sku "105"}, {:sku "120"}])
#<Var@18bc9d90: [{:sku "105"} {:sku "105"} {:sku "120"}]>
然后在每次更改时将其拆分:
user> (partition-by :sku (sort-by :sku x))
(({:sku "105"} {:sku "105"}) ({:sku "120"}))
也可以使用线程样式编写,以使流更易于阅读:
user> (->> x
(sort-by :sku)
(partition-by :sku)
(mapv vec))
[[{:sku "105"} {:sku "105"}] [{:sku "120"}]]
您可以使用和的组合(如果您希望得到向量): 可选使用以提高可读性:
(->> data
(group-by :sku)
(mapv second))
您需要使用
分组依据
功能:
(ns tst.clj.core
(:use clj.core
clojure.test
tupelo.core))
(def input [ {:id 1 :sku 105}
{:id 2 :sku 105}
{:id 3 :sku 120} ] )
(def result [ [ {:id 1 :sku 105}
{:id 2 :sku 105} ]
[ {:id 3 :sku 120} ] ] )
(deftest t-separate-by-sku
; the result of 'group-by' is a map keyed by the grouping value
; (the sku in this case)
(is (= (group-by :sku input)
{ 105 [{:id 1, :sku 105} {:id 2, :sku 105}],
120 [{:id 3, :sku 120}] } ))
; we do not care about the grouping value, so just extract
; the values from the map with 'vals'
(is (= (vals (group-by :sku input))
result)))
非常感谢。这比我想象的要容易得多。我建议不要使用
(mapv second)
函数,而是使用vals
函数从地图中提取所有值。这一点很好。但您还需要使用vec
将其包装起来,以防您需要的是精确的vector(而不是其他seq)
(->> data
(group-by :sku)
(mapv second))
(ns tst.clj.core
(:use clj.core
clojure.test
tupelo.core))
(def input [ {:id 1 :sku 105}
{:id 2 :sku 105}
{:id 3 :sku 120} ] )
(def result [ [ {:id 1 :sku 105}
{:id 2 :sku 105} ]
[ {:id 3 :sku 120} ] ] )
(deftest t-separate-by-sku
; the result of 'group-by' is a map keyed by the grouping value
; (the sku in this case)
(is (= (group-by :sku input)
{ 105 [{:id 1, :sku 105} {:id 2, :sku 105}],
120 [{:id 3, :sku 120}] } ))
; we do not care about the grouping value, so just extract
; the values from the map with 'vals'
(is (= (vals (group-by :sku input))
result)))