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