How to remove multiple keys from a map?

南楼画角 提交于 2020-07-28 11:24:56

问题


I have a function that removes a key from a map:

(defn remove-key [key map]
  (into {}
        (remove (fn [[k v]] (#{key} k))
                map)))

(remove-key :foo {:foo 1 :bar 2 :baz 3})

How do i apply this function using multiple keys?

(remove-keys [:foo :bar] {:foo 1 :bar 2 :baz 3})

I have an implementation using loop...recur. Is there a more idiomatic way of doing this in Clojure?

(defn remove-keys [keys map]
  (loop [keys keys
         map map]
    (if (empty? keys)
      map
      (recur (rest keys) (remove-key (first keys) map)))))

回答1:


Your remove-key function is covered by the standard library function dissoc. dissoc will remove more than one key at a time, but it wants the keys to be given directly in the argument list rather than in a list. So you can use apply to "flatten" it out.

(apply dissoc {:foo 1, :bar 2, :baz 3} [:foo :bar])
==> {:baz 3}



回答2:


dissoc removes one or more keys from a map:

(dissoc {:foo 1 :bar 2 :baz 3} :foo :bar)

or, if you have the keys in a collection

(apply dissoc {:foo 1 :bar 2 :baz 3} [:foo :bar])



回答3:


As others said use the built-in function instead of writing your own.

However, if this was just an example and you want an answer of how to do that if there wasn't a standard dissoc, then you can use:

(reduce (fn [m k] (remove-key k m)) {:foo 1 :bar 2 :baz 3} [:foo :bar])

Obviously, if you revert the arguments to remove-key it can be written much simpler:

(reduce remove-key {:foo 1 :bar 2 :baz 3} [:foo :bar])



回答4:


I found this type of thing and others to be super annoying in clojure, so to fix it I created the library instar: https://github.com/boxed/instar .



来源:https://stackoverflow.com/questions/9717606/how-to-remove-multiple-keys-from-a-map

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!