在 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}]}