10

我正在寻找类似于select-keys的东西:

(desired-fn {:a 1, :b 2, :c 3, :d 4} [:a :d])
;= [1 4]

;; N.B. the order of the keys in the argument seq is preserved
(= (desired-fn (array-map :a 1, :b 2, :c 3, :d 4)
               [:b :c])
   (desired-fn (array-map :d 4, :c 3, :a 1, :b 2)
               [:b :c]))
;= true

实现起来并不是特别难,虽然我还没有想出一个好名字:

(defn select-values-corresponding-to-keys [m ks]
  (for [k ks]
    (get m k)))

我是否不知道恰好满足此需求的标准功能?如果没有,其他语言(例如 Python、Ruby、Haskell)是否有此函数的名称?

4

5 回答 5

12

地图是对其键进行操作的函数:

({:a 1, :b 2} :a)
;=> 1

(map {:a 1, :b 2, :c 3, :d 4} [:a :d])
;=> (1 4)

(= (map (array-map :a 1, :b 2, :c 3, :d 4)
           [:b :c])
   (map (array-map :d 4, :c 3, :a 1, :b 2)
           [:b :c]))
;=> true

如果要将结果作为向量,只需使用vecor into [] ...,或替换mapmapv

于 2013-05-28T22:54:08.367 回答
3

map是您正在寻找的功能:

(map {:a 1 :b 2 :c 3} [:a :c])
=> (1 3)

这是有效的,因为 hashmap 本身作为一个函数(即实现clojure.lang.IFn),它返回给定它的任何键的值。

于 2013-05-29T07:09:41.060 回答
3
user=> ((juxt :a :c) {:a 1 :b 2 :c 3})
[1 3]
于 2013-05-29T07:45:47.010 回答
3

关键字本身就是函数(它们实现IFn),它们可以查看自己的映射并返回值,因此一种选择是使用juxt

(def keys-to-vals (juxt :b :c))
(= (keys-to-vals {:a 1, :b 2, :c 3, :d 4})
   (keys-to-vals {:d 4, :c 3, :a 1, :b 2}))

所以基本上你想要的 fn 现在变成了:

(defn select-vals [map keys] ((apply juxt keys) map))
于 2013-05-29T04:27:20.937 回答
1

Jay Fields 在一篇富有洞察力的博客文章 @ http://blog.jayfields.com/2011/01/clojure-select-keys-select-values-and.html中探讨了此功能和其他一些相关功能。

(几分钟前我在搜索“select-keys”时偶然发现了这一点。)

我仍然想知道某处是否有“规范”实现,所以我将问题保留为开放式。

于 2013-05-28T22:15:51.213 回答