Положить ключевые значения в карту условно, каковы краткие пути? - PullRequest
9 голосов
/ 23 марта 2011

Каковы краткие / изящные способы поместить в карту пары ключ-значение, для которых выполняются соответствующие условия?

То есть перевести

[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...}

IПодумайте об использовании слова «уменьшить» с «если» в своей лямбде, но интересуетесь более лаконичными / красивыми / элегантными / идиоматическими способами.

Ответы [ 4 ]

6 голосов
/ 24 марта 2011
(into {} (for [[c k v] (partition 3 coll) :when c] 
    [k v])) 

Основано на версии for Kintaro, но немного короче.

3 голосов
/ 23 марта 2011

Если честно, IMO, версия с reduce и if уже самая элегантная и идиоматичная см. Комментарий от 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))

Вот версия, использующая для понимания для третьего случая:

(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))

Но я думаю, что версия map от nickik лучше здесь.

2 голосов
/ 23 марта 2011

Сначала я бы подумал о том, как лучше всего отобразить ваши функциональные операции в потоке:

  1. Сгруппировать условие / ключ / значение в чанк
  2. Фильтровать чанки, гдеусловие не соответствует действительности
  3. Отбросьте условия
  4. Сгладьте куски
  5. Создайте карту из результата

Что выглядит следующим образом:

(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))

Я не уверен, что это элегантно или кратко, но я думаю, что его легко прочитать.Обратите внимание, что если вы часто имеете дело с данными в этой форме, вы можете обнаружить, что такие шаги, как (раздел 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)
1 голос
/ 23 марта 2011
(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"}

Это может быть одним из способов, но если вам нужны другие комбинации ключа условия и значения, вам необходимо изменить код. Ты не упомянул, что лучше всего будет.

Edit: Потому что это первый в вашем списке

(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)))

Потому что это весело :) 1007 *

(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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...