Clojure迭代和嵌套数据

时间:2017-05-25 23:58:06

标签: clojure

假设我有一些这样的数据:

{:gender "male" :name "Gabriel" :age 25}
{:gender "female" :name "Jane" :age 25}
{:gender "female" :name "Alice" :age 22}

我如何迭代这些数据并基于哈希嵌套它们,所以它可以是这样的:

[:25 [{:gender "male" :name "Gabriel" :age 25}, {:gender "female" :name "Jane" :age 25}] :22[ {:gender "female" :name "Alice" :age 22} ]

我已经尝试使用地图向量,我可以使用 doseq 迭代数据,但是我可以嵌套数据有很多麻烦。任何人都可以为此带来一些启示吗?非常感谢你。

2 个答案:

答案 0 :(得分:4)

一个常见的模式是将这个问题分成几部分,为每个部分创建一个表达式,然后将它们连接在一起(->>发音为"线程结束"并且它传递输出每个表达式到最后一个参数位置的下一个表达式)在这种情况下,我看到三个阶段:

  1. 按年龄对它们进行排序,以获得彼此相似的年龄
  2. 按年龄将序列拆分为块
  3. 将每个组格式化为[age-in-group whole-group
  4. 可以写成:

    user> (def my-data [{:gender "male" :name "Gabriel" :age 25}
                        {:gender "female" :name "Jane" :age 25}
                        {:gender "female" :name "Alice" :age 22}])
    #'user/my-data
    user> (->> my-data
               (sort-by :age)
               (partition-by :age)
               (map (fn [group] [(keyword (str (:age (first group)))) group]))
               reverse)
    ([:25 ({:gender "male", :name "Gabriel", :age 25}
           {:gender "female", :name "Jane", :age 25})]
     [:22 ({:gender "female", :name "Alice", :age 22})])
    

    最后的反向只是按降序排列,以便与您想要的输出样式相匹配。重要的想法是制作几个小表达式,每个表达式都会解决问题,然后组成它们来解决整个问题。

    您可能还想了解地图上的group-by功能,它会采用一系列地图,并且几乎可以直接解决您的问题。

    user> (group-by :age my-data)
    {25 [{:gender "male", :name "Gabriel", :age 25} 
         {:gender "female", :name "Jane", :age 25}], 
     22 [{:gender "female", :name "Alice", :age 22}]}
    

    它返回一个地图而不是序列(或矢量),并且不会将键转换为关键字。出于实际原因,它可能是大多数此类问题的答案。同样重要的是组成较小的解决方案,以便更方便地解决更大的问题。

答案 1 :(得分:0)

以下代码完全符合您的要求:

(def data 
  [{:gender "male" :name "Gabriel" :age 25}
   {:gender "female" :name "Jane" :age 25}
   {:gender "female" :name "Alice" :age 22}])

(vec (mapcat identity (group-by :age data)))

[25 [{:gender "male", :name "Gabriel", :age 25} 
     {:gender "female", :name "Jane", :age 25}]
 22 [{:gender "female", :name "Alice", :age 22}]]