【问题标题】:How to iterate over key/vals of a hash and return an array?如何迭代哈希的键/值并返回一个数组?
【发布时间】:2016-10-15 21:58:19
【问题描述】:

我知道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),但我正在尝试对每个键/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)类型功能。非常感谢您能分享的帮助。

【问题讨论】:

标签: clojure


【解决方案1】:

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

(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]

但我怀疑你的想法更复杂。在这种情况下,您可能会发现 Clojure Cookbook 中的 this page 上的功能很有帮助。这些从地图生成地图。

如果您正在寻找像 doseq 这样的东西,它不仅仅通过副作用起作用,那么您可能正在寻找 for

【讨论】:

  • 谢谢@Thumbnail 我想我找到了reduce-kv所需的东西
  • (vec (mapcat second data))
【解决方案2】:

由于接受的答案已经提供了执行您要求的经典方法,因此请考虑使用围绕传感器构建的更现代语言功能的这些替代方法。

  1. 如果您真的想要一个数组(如问题中所问),请使用推导来摆脱 concat 的每步延迟序列开销:

    (into-array (eduction cat (vals your-map)))
    

Eduction 是一种集合类型,每次消耗都会产生转换结果,在这种情况下特别有用,因为它直接减少到数组中(通过进入数组)并有效地减少自身

  1. 如果您不想要一个数组而是一个 Clojure 向量,您仍然可以使用传感器使用而不需要延迟开销

    (into [] cat (vals your-map))
    

在这里,除了摆脱每一步的惰性开销外,实现还在内部使用 Clojure 瞬态数据结构来加速插入操作。

请注意,这两种方法都可以使用传感器组合进行进一步扩展。您不必了解转换器是如何实现的以了解如何使用它们,知道您可以comp 它们就足够了,例如。 g.

 (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

【讨论】:

    【解决方案3】:

    如果您真正想做的只是连接映射中的值,那么只需使用valsconcat

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

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

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

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 2019-12-04
      • 2016-06-23
      • 2019-06-03
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-20
      相关资源
      最近更新 更多