从循环中的变量创建哈希

Tod*_*ddT 3 ruby arrays hash ruby-on-rails

我想最终得到一个哈希数组。

我从一系列代码开始:

@codes = ['123', '456', '789']
Run Code Online (Sandbox Code Playgroud)

我获取每个代码并使用它们调用 API,它会返回我在循环中解析为变量的值,如下所示:

@codes.each do |x|
  @y = x.get_some_data
  @brand = @y[brand]
  @size = @y[size]
end
Run Code Online (Sandbox Code Playgroud)

然后我想将这些数据放入哈希数组中

merged_array = []
final_hash = @codes.map{|code| {:code => code, :brand=> @brand, :size=> @size}
merged_array << final_hash
Run Code Online (Sandbox Code Playgroud)

在完美的世界中,最终会得到如下所示的哈希值merged_array

 {:code => '123', :brand=> 'nike', :size=> 8 }
 {:code => '456', :brand=> 'adidas', :size=> 4 }
 {:code => '789', :brand=> 'converse', :size=> 10 }
Run Code Online (Sandbox Code Playgroud)

但是当我运行脚本时,它会正确映射代码,但会覆盖@brand,@size变量并仅返回最后一个循环的值。

不确定如何将所有变量放入哈希中?

Tec*_*ton 6

在您的代码示例中,变量都被声明为实例变量,因为它们的前缀为@.

但是,循环内的变量只是工作/临时变量,而不是实例变量。此外,x.get_some_data可能不起作用,因为x它只是循环变量并包含456abc等,而不是具有所需方法的对象。因此,以下代码应该产生您想要的结果:

def get_data(codes)
  result = []
  codes.each do |code|
    y = get_some_data(code)
    result << {
      code: code,
      brand: y['brand'],
      size: y['size']
    }
  end
  result
end
Run Code Online (Sandbox Code Playgroud)

这是一个非常详细的例子;map如果 的返回值允许,您可以将整个逻辑放入 中get_some_data

更优雅的版本将利用Enumerable#each_with_object(该类Array包括Enumereable):

def get_data(codes)
  codes.each_with_object([]) do |code, result|
    y = get_some_data(code)
    result << {
      code: code,
      brand: y['brand'],
      size: y['size']
    }
  end
end
Run Code Online (Sandbox Code Playgroud)

谢谢卡里·斯沃夫兰指出这一点!

  • 一个小建议:不要在开头使用“result = []”,在结尾使用“result”,而是使用“codes.each_with_object([]) { |code, result|...”。 (2认同)