有条不紊地将键值放入映射中,有哪些简洁的方法?

时间:2011-03-23 12:54:02

标签: clojure

对于相应条件为真的映射键值对,有哪些简洁/优雅的方法?

那就是翻译

[condition1 condition2 ...] [key1 val1 key2 val2 ...]

[condition1 condition2 ...] [key1 key2 ...] [val1 val2 ...]

[condition1 key1 val1 condition2 key2 val2...]

{key-for-true-condition1 val-for-true-condition1, key-for-true-condition2 val-for-true-condition2...}

我认为在其lambda中使用“if”和“if”,但对更简洁/美丽/优雅/惯用的方式感兴趣。

4 个答案:

答案 0 :(得分:6)

(into {} (for [[c k v] (partition 3 coll) :when c] 
    [k v])) 

基于金太郎的“for”版本,但稍短一些。

答案 1 :(得分:3)

说实话IMO,reduceif的版本已经是最优雅和惯用的,请参阅下面的nickik评论。

(def coll [true :a "v1" false :b "v2" true :c "v3"])

(reduce (fn [a [c k v]] (if c (assoc a k v) a)) {} (partition 3 coll))

以下是使用for comprehension的第三种情况的版本:

(apply array-map (flatten (for [[c k v] (partition 3 coll) :when c] 
                            [k v])))

编辑:

对于第二种情况,您可以通过执行以下操作将其转换为第三种情况:

(def c [true false true])
(def k [:a :b :c])
(def v ["v1" "v2" "v3"])

(def coll (interleave c k v))

但我认为来自nickik的map版本在这里更好。

答案 2 :(得分:2)

我首先想到的是如何最好地通过流映射您的功能操作:

  1. 将条件/键/值分组到块中
  2. 过滤条件不正确的块
  3. 放弃条件
  4. 压扁块
  5. 根据结果
  6. 创建地图

    看起来像:

    (def coll [true :a "v1" false :b "v2" true :c "v3"])
    
    (apply hash-map
      (flatten 
        (map #(drop 1 %)
          (filter #(first %)
            (partition 3 coll)))))
    

    或者如果您已经感觉到了:

    (->> coll
         (partition 3)
         (filter #(first %))
         (map #(drop 1 %))
         flatten
         (apply hash-map))
    

    我不确定这是优雅还是简洁,但我认为这很容易阅读。请注意,如果您经常处理此形状的数据,您可能会发现像(partition 3 coll)或(first%)这样的步骤本身可能是有用的可重用函数,导致类似:

    (defn condition-group [coll] (partition 3 coll))
    (defn condition [group] (first group))
    (defn but-condition [group] (drop 1 group))
    (defn kv-map [kv-pairs] (apply hash-map (flatten kv-pairs)))
    
    (->> coll
         condition-group
         (filter condition)
         (map but-condition)
         kv-map)
    

答案 3 :(得分:1)

(def coll [true :key1 "value1" false :key2 "value2" true :key3 "value3"])

(defn testpair [[cond key val]]
    (when cond 
       {key val}))

(apply merge (map testpair (partition 3 coll)))
=> {:key3 "value3", :key1 "value1"}

这将是一种方式,但如果您想要条件键和值的其他组合,则必须更改代码。你没有提到女巫是最好的。

编辑: 因为它是你名单上的第一个

(def conditions [true false true] )
(def keyval [:key1 "value1"  :key2 "value2" :key3 "value3"])

(defn testpair [cond [key val]]
    (when cond 
       {key val}))

(apply merge (map testpair conditions (partition 2 keyval)))

因为它很有趣:)

(def conditions [true false true] )
(def keys [:key1 :key2 :key3])
(def vals ["value1" "value1" "value3"])


(defn testpair [cond key val]
    (when cond 
       {key val}))

(apply merge (map testpair conditions keys vals))