在 clojure 地图向量中添加和删除元素
Adding & removing elements in vector of maps in clojure
我有一个用例要在我的爱好项目中实现,我需要根据下面的一些标准在地图矢量、项目中添加和删除元素
下面是我的代码中使用的输入数据结构
Items 是一个 LazySeq
[
{
:name “Bananas”
:line-no 0
:quantity 4
}
{
:name “Apple”
:line-no 2
:quantity 3
}
]
return-quantities 是一个以 line-no 为键的 PersistentArrayMap,如下所示
{
2 1
}
我的 objective 是根据 return-数量
获取项目拆分的结果向量
[
{
:name “Bananas”
:line-no 0
:quantity 4
}
{
:name “Apple”
:line-no 2
:quantity 1
:returned? true
}
{
:name “Apple”
:line-no 2
:quantity 2
}
]
下面是我实现的示例代码
(let [items-to-be-added
(for [[line-no return-quantity] return-quantities]
(let [item (seek #(= line-no (:line-no %)) items)
item-quantity (:quantity item)
regular-item (when (pos? (- item-quantity return-quantity))
(assoc item :quantity (- item-quantity rma-quantity))
(assoc item :return-item? true))
returned-item (assoc item :quantity rma-quantity)
result [regular-item returned-item]]
result))
items-to-be-removed
(for [[line-no] return-quantities]
(let [item (seek #(= line-no (:line-no %)) items)]
item))
items-updated (filterv #(not (contains? (vec items-to-be-removed) %)) (vec items))]
(doall (flatten (concat items-updated items-to-be-added))))
上述代码的问题是过滤(从向量中删除一组元素)不起作用。有人可以帮我解决矢量过滤问题吗?还有人可以帮助我使用更高效的代码来实现这一点,因为我觉得 impl 很复杂吗?
在处理集合时使用 mapcat
为每个输入元素生成零个或多个输出元素:
(defn split-item [item quantity]
(if quantity
[(assoc item :returned? true :quantity quantity)
(update item :quantity - quantity)]
[item]))
(defn split-items [items quantities]
(vec (mapcat #(split-item % (quantities (:line-no %))) items)))
(def items
[{:name "Bananas", :line-no 0, :quantity 4}
{:name "Apple", :line-no 2, :quantity 3}])
(def return-quantities
{2 1})
(split-items items return-quantities)
=> [{:name "Bananas", :line-no 0, :quantity 4}
{:name "Apple", :line-no 2, :quantity 1, :returned? true}
{:name "Apple", :line-no 2, :quantity 2}]
(def items [{:name “Bananas”
:line-no 0
:quantity 4}
{:name “Apple”
:line-no 2
:quantity 3}])
(def return-quantities
{0 3
2 1})
(defn add-return [items-by-line-no line-no return-quantity]
(let [item (first (get items-by-line-no line-no))
item-decreased (update item :quantity - return-quantity)
item-returned (assoc item :quantity return-quantity :returned? true)]
(update items-by-line-no line-no #(conj (assoc % 0 item-decreased) item-returned))))
(pprint (reduce-kv add-return (group-by :line-no items) return-quantities))
;; {0
;; [{:name "Bananas", :line-no 0, :quantity 1}
;; {:name "Bananas", :line-no 0, :quantity 3, :returned? true}],
;; 2
;; [{:name "Apple", :line-no 2, :quantity 2}
;; {:name "Apple", :line-no 2, :quantity 1, :returned? true}]}
我有一个用例要在我的爱好项目中实现,我需要根据下面的一些标准在地图矢量、项目中添加和删除元素
下面是我的代码中使用的输入数据结构
Items 是一个 LazySeq
[
{
:name “Bananas”
:line-no 0
:quantity 4
}
{
:name “Apple”
:line-no 2
:quantity 3
}
]
return-quantities 是一个以 line-no 为键的 PersistentArrayMap,如下所示
{
2 1
}
我的 objective 是根据 return-数量
获取项目拆分的结果向量[
{
:name “Bananas”
:line-no 0
:quantity 4
}
{
:name “Apple”
:line-no 2
:quantity 1
:returned? true
}
{
:name “Apple”
:line-no 2
:quantity 2
}
]
下面是我实现的示例代码
(let [items-to-be-added
(for [[line-no return-quantity] return-quantities]
(let [item (seek #(= line-no (:line-no %)) items)
item-quantity (:quantity item)
regular-item (when (pos? (- item-quantity return-quantity))
(assoc item :quantity (- item-quantity rma-quantity))
(assoc item :return-item? true))
returned-item (assoc item :quantity rma-quantity)
result [regular-item returned-item]]
result))
items-to-be-removed
(for [[line-no] return-quantities]
(let [item (seek #(= line-no (:line-no %)) items)]
item))
items-updated (filterv #(not (contains? (vec items-to-be-removed) %)) (vec items))]
(doall (flatten (concat items-updated items-to-be-added))))
上述代码的问题是过滤(从向量中删除一组元素)不起作用。有人可以帮我解决矢量过滤问题吗?还有人可以帮助我使用更高效的代码来实现这一点,因为我觉得 impl 很复杂吗?
在处理集合时使用 mapcat
为每个输入元素生成零个或多个输出元素:
(defn split-item [item quantity]
(if quantity
[(assoc item :returned? true :quantity quantity)
(update item :quantity - quantity)]
[item]))
(defn split-items [items quantities]
(vec (mapcat #(split-item % (quantities (:line-no %))) items)))
(def items
[{:name "Bananas", :line-no 0, :quantity 4}
{:name "Apple", :line-no 2, :quantity 3}])
(def return-quantities
{2 1})
(split-items items return-quantities)
=> [{:name "Bananas", :line-no 0, :quantity 4}
{:name "Apple", :line-no 2, :quantity 1, :returned? true}
{:name "Apple", :line-no 2, :quantity 2}]
(def items [{:name “Bananas”
:line-no 0
:quantity 4}
{:name “Apple”
:line-no 2
:quantity 3}])
(def return-quantities
{0 3
2 1})
(defn add-return [items-by-line-no line-no return-quantity]
(let [item (first (get items-by-line-no line-no))
item-decreased (update item :quantity - return-quantity)
item-returned (assoc item :quantity return-quantity :returned? true)]
(update items-by-line-no line-no #(conj (assoc % 0 item-decreased) item-returned))))
(pprint (reduce-kv add-return (group-by :line-no items) return-quantities))
;; {0
;; [{:name "Bananas", :line-no 0, :quantity 1}
;; {:name "Bananas", :line-no 0, :quantity 3, :returned? true}],
;; 2
;; [{:name "Apple", :line-no 2, :quantity 2}
;; {:name "Apple", :line-no 2, :quantity 1, :returned? true}]}