14

マップ上のキーに値があるかどうかを確認する慣用的な方法は何ですか?たとえば、次の場合:

=> (def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}])

:foo == 0のすべてのマップを見つけるには、次のようにします。

=> (filter (comp zero? :foo) seq-of-maps)
({:foo 0, :bar "baz"})

しかし、:bar == "hi"ですべてのマップを検索したい場合、私が考えることができる最良のものは次のとおりです。

=> (filter #(= (:bar %) "hi") seq-of-maps)
({:foo 1, :bar "hi"})

あまり読みにくいです。それを行うためのより良い/より慣用的な方法はありますか?

4

7 に答える 7

15

慣用句は主観的ですが、私はします

=> (filter (comp #{"hi"} :bar) seq-of-maps)

またはあなたがしたこと。

于 2012-08-01T23:51:04.087 に答える
5

私は個人的に、この種のものをリファクタリングして、明確に名前が付けられた高階関数を使用するのが好きです。

(def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}])

(defn has-value [key value]
  "Returns a predicate that tests whether a map contains a specific value"
  (fn [m]
    (= value (m key))))

(filter (has-value :bar "hi") seq-of-maps)
=> ({:foo 1, :bar "hi"})

欠点は、管理および保守するための追加の関数定義が提供されることですが、エレガンス/コードの可読性はそれだけの価値があると思います。このアプローチは、述語を何度も再利用する場合、パフォーマンスの観点からも非常に効率的です。

于 2012-08-02T01:58:07.977 に答える
3

clojure.set/indexもここで使用できます

((index seq-of-maps [:foo]) {:foo 0})
((index seq-of-maps [:bar]) {:bar "hi"})

必要に応じて、関数でラップできます

(defn select-maps [xrel m]
   ((index xrel (keys m)) m))

それから

(select-maps seq-of-maps {:foo 0})
(select-maps seq-of-maps {:bar "hi"})

両方とも機能します-インデックスを使用して複数のキー/値を持つマップをリクエストすることもできます。

(select-maps seq-of-maps {:foo 0 :bar "baz"}) 

foo0とbar"baz"を含むすべてのマップを選択します

于 2012-08-02T00:48:41.807 に答える
2

匿名関数をフィルターに渡す3番目の例は、特定の値を持つマップを見つけるためのより理想的な方法の1つのようです。とても読みやすいと思いました。

于 2012-08-02T00:07:57.847 に答える
2
user> (def seq-of-maps [{:foo 1 :bar "hi"} {:foo 0 :bar "baz"}])
#'user/seq-of-maps
user> (filter #(-> % :bar (= "hi")) seq-of-maps)
({:foo 1, :bar "hi"})

Pepijnが言うように、私は慣用的な方法は個人的な意見によって異なると思います。->ネストされた括弧を抽出するためにマクロを使用することがあります。

于 2012-08-02T00:49:42.307 に答える
0

あなたのコードは私にはうまく見えます。他の可能な解決策は、for以下に示すようにマクロを使用することです。

(for [m seq-of-maps 
      :let [v (:bar m)] 
      :when (= v "hi")] 
   m)
于 2012-08-02T04:07:26.063 に答える
0

zero?次の(partial = "hi")ように置き換えるだけです。

=> (filter (comp (partial = "hi") :bar) seq-of-maps)
于 2012-08-02T04:08:37.823 に答える