如何迭代哈希的键/值并返回一个数组?

时间:2016-10-15 21:58:19

标签: clojure

我了解doseq会迭代{ ... }文字的每个键/值,如下例所示:How to Iterate Over Map Keys and Values?但是,doseq会返回nil我希望迭代都返回一个值。

我有一个key / val对象,如下所示:

{:keyAAA [ val_element_one val_element_two val_element_three ]
 :keyBBB [ val_element_four val_element_five val_element_six ]
 :keyCCC [ val_element_seven val_element_eight val_element_nine ]}

我希望创建一个返回如下值的函数:

( :keyAAA :keyBBB :keyCCC )

我知道我可以在这个特定的例子中使用(keys map),但我正在尝试用每个key / val"元素"做更复杂的事情。我需要一个迭代key / val对象的函数,返回一个填充了每个"元素"的列表/数组。具体来说,我想最终返回看起来像这样的东西:

[ val_element_one 
  val_element_two 
  val_element_three 
  val_element_four 
  val_element_five 
  val_element_six
  val_element_seven 
  val_element_eight 
  val_element_nine ]

基本上,我在对象的每个键/值上寻找map(或甚至更好的reduce)类型功能。我非常感谢你能分享的帮助。

3 个答案:

答案 0 :(得分:4)

我们可以按如下方式处理您的具体问题:

(def data
  '{
    :keyAAA [ val_element_one val_element_two val_element_three ]
    :keyBBB [ val_element_four val_element_five val_element_six ]
    :keyCCC [ val_element_seven val_element_eight val_element_nine ]
    })

(->> data
     vals
     (apply concat)
     vec)

;[val_element_one val_element_two val_element_three val_element_four val_element_five val_element_six val_element_seven val_element_eight val_element_nine]

但我怀疑你有一些更复杂的想法。在这种情况下,您可以从this pageClojure Cookbook处找到有用的功能。这些从地图生成地图。

如果你正在寻找像doseq这样的东西,而不仅仅是副作用,那么你可能正在寻找for

答案 1 :(得分:2)

由于已接受的答案已经提供了经典的方法来做你要求考虑的这些替代方法,使用更多现代语言功能建立在传感器周围。

  1. 如果你真的想要一个数组(就像问题中的问题一样),可以使用eduction去除concat的每步开销的懒惰序列:

    (into-array (eduction cat (vals your-map)))
    
  2. Eduction是一种集合类型,可以根据消耗产生转换结果,在这种情况下特别有用,因为它直接缩减为数组(通过数组)并有效降低自身

    1. 如果你不想要一个阵列而不是Clojure矢量,你仍然可以使用传感器使用

      而不会产生懒惰的开销。
      (into [] cat (vals your-map))
      
    2. 除了摆脱懒惰的每步开销外,该实现还在内部使用Clojure瞬态数据结构来加速插入操作。

      请注意,这样做的两种方式都可以使用换能器组合进一步扩展。您不必了解传感器是如何实现的,以了解如何使用它们,只需知道您可以comp它们,e。克。

       (into [] (comp cat (filter pos?)) (vals your-map)) ; just the positive elements
      

      最后,如果你意识到你以后确实需要懒惰,很容易在不重写任何代码的情况下得到它:

       (sequence (comp cat (filter pos?)) (vals your-map)) 
       ;; now it's up to the consumer of your collection how many   
       ;; elements will be calculated
      

答案 2 :(得分:0)

如果您真正想要的是连接地图中的值,那么只需使用valsconcat

(apply concat (vals <your-map>))

如果它实际上比这更复杂,您可以使用mapcat。以下是使用mapcat连接值的方法:

(mapcat (fn [[k v]] ;; Or just use second
          v)
        <your-map>)