从以数组为值的哈希中获取数组

Posted

技术标签:

【中文标题】从以数组为值的哈希中获取数组【英文标题】:Get array from hash with arrays as values 【发布时间】:2017-07-04 21:32:13 【问题描述】:

给定以下哈希hash,其中键作为符号,值作为数组:

hash
#=> :stage_item=>[:stage_batch_id, :potential_item_id], :item=>[:id, :size, :color, :status, :price_sold, :sold_at], :style=>[:wholesale_price, :retail_price, :type, :name]

我如何获得一个仅将值(数组)相加的数组?

我知道我可以使用#each_with_object#flatten

hash.each_with_object([])  |(k, v), array| array << v .flatten
#=> [:stage_batch_id, :potential_item_id, :id, :size, :color, :status, :price_sold, :sold_at, :wholesale_price, :retail_price, :type, :name]

但我希望只有 #each_with_object 可以工作:

hash.each_with_object([])  |(k, v), array| array += v 
#=> []

虽然每个 with 对象的重点是它跟踪累加器(在这种情况下名为 array),所以我可以像下面的示例一样 += 它:

arr = [1,2,3]
#=> [1, 2, 3]
arr += [4]
#=> [1, 2, 3, 4]

我错过了什么?

【问题讨论】:

【参考方案1】:

Array &lt;&lt; .. 就地更改原始数组:

irb(main):014:0> a = original = []
=> []
irb(main):015:0> a << [1]
=> [[1]]
irb(main):016:0> a
=> [[1]]
irb(main):017:0> original
=> [[1]]
irb(main):018:0> a.equal? original  # identity check
=> true

Array += .. 在不改变原数组的情况下返回一个新数组:

irb(main):019:0 a = original = []
=> []
irb(main):020:0> a += [1]
=> [1]
irb(main):021:0> a
=> [1]
irb(main):022:0> original
=> []
irb(main):023:0> a.equal? original
=> false

根据Enumerable#each_with_object documentation,

使用任意对象迭代每个元素的给定块 给定,并返回最初给定的对象。

如果没有给出块,则返回一个枚举器。

所以,如果是+=,则返回未修改的初始空数组。


顺便说一句,您可以简单地使用Hash#values method,而不是使用each_with_object,它会返回一个填充了哈希值的新数组:

hash.values.flatten

【讨论】:

【参考方案2】:

如果你坚持使用Array#+,实际上inject会更合适:

hash.inject([])  |a, (_, v)| a + v 

您通常使用each_with_object 而不是inject 的原因是,如果您想就地累积结果而不是使用块的返回值作为累加器。在这种情况下,array1 + array2 返回连接,因此您不需要使用修改备忘录对象的运算符(或方法),因为 Array#+ 返回您想要输入下一个循环的内容。

虽然我们在这里,但这些会更简单:

hash.values.flatten
hash.values.inject(:+)
h.values.flat_map(&:itself)

如果您真的喜欢调用该方法,第二个甚至使用Array#+

【讨论】:

以上是关于从以数组为值的哈希中获取数组的主要内容,如果未能解决你的问题,请参考以下文章

Perl如何访问作为另一个哈希值的数组元素的哈希?

以数组为值对哈希表进行排序

如何合并散列数组以获取值数组的散列

哈希是什么?为什么哈希存取比较快?

Ruby中数组哈希的所有可能组合

TypeaheadJS 方法未将数组转换为值