Я написал функцию для "поворота" некоторых таблиц данных, но мне интересно, есть ли более простой способ добиться того же результата.
(defn pivot-ab-ba
[data]
(r/reduce
(fn [result [ks c]]
(assoc-in result ks c))
{}
;; pivot {a [b1 c1 b2 c2]} => [[b1 a] c1] [[b2 a] c2]
(mapcat (fn [[a bcseq]]
;; pivot [a [b c]] => [[[b a] c]]
(mapcat (fn [[b c]] [[[b a] c]]) bcseq))
data)))
(let [data {1 {:good [1 2] :bad [3 4]}
2 {:good [5 6] :bad [7 8]}}]
(pivot-ab-ba data))
; => {:good {1 [1 2], 2 [5 6]}, :bad {1 [3 4], 2 [7 8]}}
Это работает, но кажется слишком сложным.
ОБНОВЛЕНИЕ:
@ ТейлорВуд предложила решение ниже;вот этот ответ с модификацией, чтобы не передавать вводимые ключи:
(defn pivot [data]
(reduce-kv
(fn [acc k v]
(reduce (fn [acc' k'] (assoc-in acc' [k' k] (k' v)))
acc
(keys v)))
{}
data))
ОБНОВЛЕНИЕ 2: Спасибо всем за ваши ответы.Поскольку существует такое разнообразие ответов, я представил результаты, чтобы получить представление о том, как они выполнялись.По общему признанию, это - единственный тест, но все еще интересный:
Benchmarks performed with (criterium.core/bench pivot-function)
# Original pivot-ab-ba
Evaluation count : 8466240 in 60 samples of 141104 calls.
Execution time mean : 7.274613 µs
Execution time std-deviation : 108.681498 ns
# @TaylorWood - pivot
Evaluation count : 39848280 in 60 samples of 664138 calls.
Execution time mean : 1.568971 µs
Execution time std-deviation : 32.567822 ns
# @AlanThompson - reorder-tree
Evaluation count : 25999260 in 60 samples of 433321 calls.
Execution time mean : 2.385929 µs
Execution time std-deviation : 33.130731 ns
# @AlanThompson reorder-tree-reduce
Evaluation count : 14507820 in 60 samples of 241797 calls.
Execution time mean : 4.249135 µs
Execution time std-deviation : 89.933197 ns
# @amalloy - pivot
Evaluation count : 12721980 in 60 samples of 212033 calls.
Execution time mean : 5.087314 µs
Execution time std-deviation : 226.242206 ns