将哈希推入数组

时间:2017-08-07 17:57:45

标签: ruby-on-rails ruby ruby-on-rails-4

我将这些哈希作为输出,我需要将其推入数组而不会覆盖。

output1= {:user_id=>9, :project_id=>4, :task_id=>87,  :comment=>"Test 20"}
output2 = {:user_id=>9, :project_id=>12, :task_id=>105,:comment=>"Test 21"}

当我遍历循环时,我需要将这2个输出推送到单个数组中。现在发生的事情是,当我将第二个输出推入数组时,它会覆盖第一个输出,而下面是我得到的结果。

Entry_array=[{:user_id=>9,:project_id=>12,:task_id=>105,:comment=>"Test 21"}, 
{:user_id=>9, :project_id=>12, :task_id=>105,:comment=>"Test 21"}]

我希望将hash output1和hash output2的结果组合在一起。 谢谢你的帮助。

这是我正在使用的代码

   attributes =[:user_id,:project_id,task_id,:comment]
   entry_array=[]
   output = {}

   CSV.foreach(csv_file, headers: true, converters: :date).with_index do |row,line_no|
   entry_hash= row.to_hash
   .....some code here where we get the entry_hash....
     i=0

     entry_array <<output
   end 

3 个答案:

答案 0 :(得分:2)

这种情况发生的原因,至少根据您的代码,因为您对每一行使用相同的output哈希。如果你跑了

puts entry_array.collect(&:object_id)

在CSV文件的末尾,您会看到它们都是同一个对象。因此,即使您将其放入每行末尾的数组中,您仍然在修改同一个对象,该数组现在指向该对象。基本上你正在做的是

a = { hello: 'world' } # => {:hello=>"world"}
b = a                  # => {:hello=>"world"}
b[:hello] = 'there'
a                      # => {:hello=>"there"}
b                      # => {:hello=>"there"}

# storing it in an array does the same thing
output = { hello: 'world' } # => {:hello=>"world"}
array = [output]            # => [{:hello=>"world"}]
output[:hello] = 'there'
output                      # => {:hello=>"there"}
array                       # => [{:hello=>"there"}]

解决这个问题需要做的是为每一行实例化一个新哈希:

attributes = [:user_id, :project_id, :task_id, :comment]
entry_array = []

CSV.foreach(csv_file, headers: true, converters: :date).with_index do |row, line_no|
  output = { } # Instantiate here, inside the loop, so each row gets its own hash
  entry_hash = row.to_hash

  # if you need the key for something, use this
  # entry_hash.each.with_index do |(key, value), index|
  # otherwise, just iterate over each value
  entry_hash.each_value.with_index do |value, index|
    output[attributes[index]] = value.is_a?(Array) ? value.first.to_i : value
  end

  entry_array << output
end

我已将班级检查更改为is_a?并删除了i计数器以支持在迭代中使用with_index,而您没有使用key在显示的示例中,我刚刚使用了each_value,但是如果您使用的是each_index,则会在哈希上留下评论,说明如何将eachkey一起使用没有显示。

答案 1 :(得分:1)

我认为这正是您所寻找的:https://apidock.com/ruby/Enumerator/each_with_index。 我猜你使用的i会在迭代之间刷新:)。

答案 2 :(得分:0)

我不确定这是让梦想成真的最好方法,但这是一种方式

1)创建你的数组

arr_of_hashes = []

2)现在您已拥有阵列,可以使用哈希填充它

output1= {:user_id=>9, :project_id=>4, :task_id=>87,  :comment=>"Test 20"}
output2 = {:user_id=>9, :project_id=>12, :task_id=>105,:comment=>"Test 21"}

arr_of_hashes << output1
arr_of_hashes << output2
...

3)现在当你检查arr_of_hashes的值时,你会得到

[{:user_id=>9, :project_id=>4, :task_id=>87, :comment=>"Test 20"}, {:user_id=>9, :project_id=>12, :task_id=>105, :comment=>"Test 21"}]

我希望这有助于:)

快乐黑客

CSV.foreach(csv_file, headers: true, converters: :date).with_index do |row,line_no|

 .....some code here where we get the entry_hash....

   entry_array = [] # you need to define the element first before you can add stuff to it :) 
   entry_hash.each do |key,value|
        if value.class == Array
          output[attributes[i]] = value.first.to_i
        else
          output[attributes[i]] = value
        end
         i += 1
     end
     entry_array <<output
   end 
相关问题