从以数组为值的散列中获取数组
Get array from hash with arrays as values
给定以下哈希 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
and #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]
我错过了什么?
Array << ..
改变原数组 in-place:
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
while, Array += ..
returns 不改变原数组的新数组:
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,
Iterates the given block for each element with an arbitrary object
given, and returns the initially given object.
If no block is given, returns an enumerator.
因此,在 +=
的情况下,returns 未修改的初始空数组。
顺便说一句,您可以简单地使用 Hash#values
method 而不是使用 each_with_object
,其中 returns 一个新数组填充了散列中的值:
hash.values.flatten
如果你坚持使用Array#+
:
,实际上inject
会更合适
hash.inject([]) { |a, (_, v)| a + v }
您通常使用 each_with_object
而不是 inject
的原因是如果您想要累加结果 in-place 而不是使用块的 return 值作为累加器。在这种情况下,array1 + array2
return 是串联,因此您不需要使用修改备忘录对象的运算符(或方法),因为 Array#+
return 是您想要的进入下一个周期。
虽然我们在这里,但这些会更简单:
hash.values.flatten
hash.values.inject(:+)
h.values.flat_map(&:itself)
如果你真的喜欢调用那个方法,第二个甚至使用 Array#+
。
给定以下哈希 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
and #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]
我错过了什么?
Array << ..
改变原数组 in-place:
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
while, Array += ..
returns 不改变原数组的新数组:
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,
Iterates the given block for each element with an arbitrary object given, and returns the initially given object.
If no block is given, returns an enumerator.
因此,在 +=
的情况下,returns 未修改的初始空数组。
顺便说一句,您可以简单地使用 Hash#values
method 而不是使用 each_with_object
,其中 returns 一个新数组填充了散列中的值:
hash.values.flatten
如果你坚持使用Array#+
:
inject
会更合适
hash.inject([]) { |a, (_, v)| a + v }
您通常使用 each_with_object
而不是 inject
的原因是如果您想要累加结果 in-place 而不是使用块的 return 值作为累加器。在这种情况下,array1 + array2
return 是串联,因此您不需要使用修改备忘录对象的运算符(或方法),因为 Array#+
return 是您想要的进入下一个周期。
虽然我们在这里,但这些会更简单:
hash.values.flatten
hash.values.inject(:+)
h.values.flat_map(&:itself)
如果你真的喜欢调用那个方法,第二个甚至使用 Array#+
。