当另一个Vector

时间:2016-09-26 12:33:16

标签: clojure

我有以下数据结构(我相信两张地图)

{ :put [{:listId "myList", :entryId "1", :dateTime 1434637074},
        {:listId "myList", :entryId "2", :dateTime 1434637075}],
  :delete [{:listId "myList", :entryId "1"}]}

并希望删除:put中已存在密钥listIdentryId的所有:delete条目。结果应该是:

{ :put [{:listId "myList", :entryId "2", :dateTime 1434637075}],
  :delete [{:listId "myList", :entryId "1"}]}

我尝试了以下但是1)它不是惯用的Clojure和2)它不会删除重复的条目。

(defn remove-add-if-duplicate [requests]
  (doseq [delete (seq (:delete requests))]
    (doseq [put (seq (:put requests)) 
            :when (and (= (:listId delete) (:listId put))
                       (= (:entryId delete) (:entryId put))]
      (disj (set (:put requests)) put)))
  requests))

(remove-add-if-duplicate 
  { :put [{:listId "myList", :entryId "1", :dateTime 1434637074},
          {:listId "myList", :entryId "2", :dateTime 1434637075}],
    :delete [{:listId "myList", :entryId "1"}]})

你能帮助我修改我的代码或向我展示一个很好的方法吗?

2 个答案:

答案 0 :(得分:2)

(defn strip [data]
  (let [ks (-> data :delete set)]
    (update-in data [:put] #(remove (fn [m] (ks (select-keys m [:listId :entryId]))) %))))

例如,......

(def my-stuff { :put [{:listId "myList", :entryId "1", :dateTime 1434637074},
        {:listId "myList", :entryId "2", :dateTime 1434637075}],
  :delete [{:listId "myList", :entryId "1"}]})

(def processed { :put [{:listId "myList", :entryId "2", :dateTime 1434637075}],
  :delete [{:listId "myList", :entryId "1"}]})

(= (strip my-stuff) processed);
;true

这与McSokoli's answer基本相同,但

  • 作为函数呈现,
  • 使用集合而不是some来测试状态,
  • 使用update-in应用于整个数据结构。

您误解了Clojure数据结构的工作方式。处理它们的功能不会改变它们;相反,他们返回修改后的版本。

您使用doseq是一种赠品。这返回nil,因此只有副作用,在这种情况下没有副作用;也不应该。

您可以for使用:where来获得remove的效果,但是没有意义。

答案 1 :(得分:1)

这应该可以胜任。 我们使用select-keys仅保留来自输入:listId中的条目的密钥(及其值):entryId:put,以及remove这样的条目在(:delete input)中找到。

(def input {:put [{:listId "myList", :entryId "1", :dateTime 1434637074},
                  {:listId "myList", :entryId "2", :dateTime 1434637075}],
            :delete [{:listId "myList", :entryId "1"}]}


(defn filtered [input]
  {:delete (:delete input)
   :put (remove #(some #{(select-keys % [:listId :entryId])} 
               (:delete input))    
        (:put input))})

测试它我们得到这个:

user> (filtered input)
{:delete [{:listId "myList", :entryId "1"}], 
 :put ({:listId "myList", :entryId "2", :dateTime 1434637075})}

或更多数据

user> (filtered {:put [{:listId "myList", :entryId "1", :dateTime 1434637074},
                       {:listId "myList", :entryId "2", :dateTime 1434637075}
                       {:listId "other", :entryId "3", :dateTime 1434637076}
                       {:listId "bestList", :entryId "4", :dateTime 1434637076}],
                :delete [{:listId "myList", :entryId "1"}
                         {:listId "bestList" :entryId "4"}]})
{:delete [{:listId "myList", :entryId "1"} {:listId "bestList", :entryId "4"}],
 :put ({:listId "myList", :entryId "2", :dateTime 1434637075}
       {:listId "other", :entryId "3", :dateTime 1434637076})}