Clojure:使用另一个映射中的切换键和值创建映射
我试图从一个输入Clojure:使用另一个映射中的切换键和值创建映射,clojure,Clojure,我试图从一个输入map创建一种还原索引。我得到的输入映射是: {"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}} 然后我想得到另一张地图作为结果: {"a" ["id-1" "id-2"], "b" ["id-1" "id-2"], "c" ["id-1" "id-2"]} 然而,我认为我的思想确实疯了,我认为我把自己画进了角落,却无法跳出框框思考。这是我到目前为止得到的,看起来很臭: (->> {
map
创建一种还原索引。我得到的输入映射是:
{"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}}
然后我想得到另一张地图作为结果:
{"a" ["id-1" "id-2"], "b" ["id-1" "id-2"], "c" ["id-1" "id-2"]}
然而,我认为我的思想确实疯了,我认为我把自己画进了角落,却无法跳出框框思考。这是我到目前为止得到的,看起来很臭:
(->> {"id-1" {"values" ["a" "b" "c"]} "id-2" {"values" ["a" "b" "c"]}}
(map #(->> (get (second %) "values")
(map (fn [x y] (hash-map y x)) (into [] (repeat (count (get (second %) "values")) (first %))))
(apply merge-with concat)))
(apply merge-with concat))
基本上,我使用第一个映射来“迭代”所有输入值。然后,我使用第二个贴图创建一系列单独的贴图,如下所示:
({"a" "id-2"} {"b" "id-2"} {"c" "id-2"} {"a" "id-1"} {"b" "id-1"} {"c" "id-1"})
为了获得该映射,我使用到[](repeat..)
创建了一个中间数组,将值数组与映射一起馈送
然后我把它们合并在一起,得到我的期望值
这里有两个问题:
这看起来比我的直觉要复杂得多
目前的最终结果还不完美,因为我得到了以下结果:
{“a”(\i\d-\1\i\d-\2),“b”(\i\d-\1\i\d-\2),“c”(\i\d-\1\i\d-\2)}
鉴于这一投入:
(def input {"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}})
这样做更容易:
(defn extract [key values]
(for [v (get values "values")] {v [key]}))
(->> input
(mapcat (partial apply extract))
(apply merge-with concat))
或者,在没有附加功能的情况下:
(->> (for [[k vs] input]
(for [v (get vs "values")] {v [k]}))
(flatten)
(apply merge-with concat))
这正是你想要的
诀窍是在提取
函数中将键
包装在向量中,这样与concat合并
就可以在不连接字符串的情况下工作。给定此输入:
(def input {"id-1" {"values" ["a" "b" "c"]}, "id-2" {"values" ["a" "b" "c"]}})
这样做更容易:
(defn extract [key values]
(for [v (get values "values")] {v [key]}))
(->> input
(mapcat (partial apply extract))
(apply merge-with concat))
或者,在没有附加功能的情况下:
(->> (for [[k vs] input]
(for [v (get vs "values")] {v [k]}))
(flatten)
(apply merge-with concat))
这正是你想要的
诀窍是在提取
函数中将键
包装在向量中,这样与concat合并
就可以在不连接字符串的情况下工作。使用:
清晰的
(apply merge-with into
(for [[k m] input
v (get m "values")]
{v [k]}))
使用:
清晰的
(apply merge-with into
(for [[k m] input
v (get m "values")]
{v [k]}))
谢谢,它完全按照预期工作,当然比我做的要干净得多。然而,我不清楚partial
在这种情况下是如何工作的,你能详细说明一下它是如何工作的吗?@Neoasimov它基本上创建了一个函数,该函数接受一个参数(或更多),然后用该参数调用apply extract
。比#(应用摘录%)
更好,IMHO.ok很好,谢谢您的解释。是的,我注意到了这个变体,我正在分析它。这个例子非常有助于在Clojure中找到处理此类数据的新方法,谢谢!我得到了我所需要的一切,甚至更多:)也许是最后一个问题,是否有办法获得结果值的数组(目前是一个列表;这是我在测试中遇到的另一个问题)。需要将放在[]
的某个地方,但不确定放在哪里:|只需将最后一行更改为(应用合并(comp-vec-concat))
concat
创建一个惰性序列,然后您可以使用vec
将其转换为向量。谢谢,它完全按照预期工作,而且肯定比我做的要干净得多。然而,我不清楚partial
在这种情况下是如何工作的,你能详细说明一下它是如何工作的吗?@Neoasimov它基本上创建了一个函数,该函数接受一个参数(或更多),然后用该参数调用apply extract
。比#(应用摘录%)
更好,IMHO.ok很好,谢谢您的解释。是的,我注意到了这个变体,我正在分析它。这个例子非常有助于在Clojure中找到处理此类数据的新方法,谢谢!我得到了我所需要的一切,甚至更多:)也许是最后一个问题,是否有办法获得结果值的数组(目前是一个列表;这是我在测试中遇到的另一个问题)。需要将放在[]
的某个地方,但不确定放在哪里:|只需将最后一行更改为(应用合并(comp-vec-concat))
concat
创建一个惰性序列,然后您可以使用vec
将其转换为向量。@a-webb这真是太好了!但我不确定我是否完全明白了。你能解释一下[[k{vs“values”}]input,v vs]
会发生什么吗?我想这是我第一次看到这种解构语法。我的理解是,k
绑定到键id-x
,然后vs
绑定到向量或值(不确定{}
如何影响解构)。但是,,v vs
,这是不是要对刚解构的内容进行解构,以便v
与先前解构的值绑定?如果是这样,是否有关于这种解构语法的文档?@Neoasimov这种语法,(让[{a-value:a}my map])
将映射中:a
键的值绑定到a-value
。,v vs
,是的的延续,如(对于[row[[1 2 3][4 5 6]],element row]元素);=>(123456)
。逗号只是空白,通常你会看到换行符和缩进。@a.Webb我比公认的答案更喜欢这个答案;就风格而言,我喜欢(对于[[k m]输入,v(get m“values”)]…)
更好一点,如果只是因为使用显式映射分解风格有点不寻常的话。+1同意,它比我的好:-)不知道可以使用字符串键来分解哈希映射。我一直认为它只适用于符号:-(@sloth我想你指的是关键词,不是符号。太可爱了!@a-webb这真的很好!但我不确定我是否完全理解它。你能解释一下[[k{vs“values”}]输入,v vs]会发生什么吗
,我想这是我第一次看到这种解构语法。我理解的是k
绑定到键id-x
,然后vs
绑定到向量或值(不确定{}
如何影响解构)。但是,,v vs
,是不是要对刚解构的内容进行解构,以便v
与前面的解构值绑定?如果是,是否有关于这种解构语法的文档?@Neoasimo