从以数组为值的哈希中获取数组
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 << ..
就地更改原始数组:
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#+
。
【讨论】:
以上是关于从以数组为值的哈希中获取数组的主要内容,如果未能解决你的问题,请参考以下文章