通过循环将Ruby数组转换为哈希

时间:2016-02-28 09:40:27

标签: arrays ruby json hash

我试图通过迭代将数组转换为哈希。我有以下数组:

weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]]

我循环遍历数组以创建一个像这样的哈希:

hash_weekdays = Hash.new
weekdays.each do |item|
  hash_weekdays["weekday"] = item[0]
  hash_weekdays["number"] = item[1]
end

然而,这仅显示我最后一个工作日。关于从哪里去的任何想法?谢谢!

3 个答案:

答案 0 :(得分:1)

散列包含键值对。每个键仅引用一个值,每个键在散列中是uniq。您的密钥weekdaynumber的值将在每次迭代时被覆盖。这就是你只得到最后一次迭代结果的原因。

您可以将其转换为哈希数组作为替代。

weekdays.map{|day, number| {weekday:day, number: number}}
# => [{:weekday=>"Monday", :number=>2}, {:weekday=>"Tuesday", :number=>4}, {:weekday=>"Thursday", :number=>5}]

如果您的工作日或数字在主阵列中是唯一的,您可以使用其中一种作为键,另一种作为哈希值。

weekdays.to_h
# => {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}

weekdays.to_h.invert
# => {2=>"Monday", 4=>"Tuesday", 5=>"Thursday"}

答案 1 :(得分:1)

你可以这样做:

weekdays.to_h #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}

或修复您的代码:

weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]]

hash_weekdays = Hash.new
weekdays.each do |item|
  hash_weekdays[item[0]] = item[1]
end

p hash_weekdays #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}

答案 2 :(得分:1)

您需要将代码更改为以下内容:

hash_weekdays = Hash.new
weekdays.each do |item|
  hash_weekdays[item[0]] = item[1]
end
hash_weekdays
 #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

weekdays["Monday",2])的第一个元素传递给块时,块变量被赋值为:

item = ["Monday",2]

由于您需要引用item的每个元素,因此使用两个块变量是很常见的,这两个块变量的值是使用并行赋值分配的(又名多个赋值< / em>的):

day, nbr = ["Monday",2]
    #=> ["Monday", 2] 
day #=> "Monday" 
nbr #=> 2 

这允许你写

hash_weekdays = {} # the more common way of writing hash_weekdays = Hash.new
weekdays.each { |day, nbr| hash_weekdays[day] = nbr } # used {...} rather than do..end
hash_weekdays

这可以说是更清楚。

请注意,您首先将hash_weekdays初始化为空哈希,然后如果您希望获取哈希值的新值(作为方法的最后一行,则需要最后一行hash_weekdays,例如)。您可以使用方法Enumerable#each_with_object

将其减少为单行(非常类似于Ruby)
weekdays.each_with_object({}) { |item, hash_weekdays| hash_weekdays[item[0]] = item[1] }
  #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

请注意,这使用并行分配。传递给块[["Monday", 2], {}]的第一个元素按如下方式分配:

item, hash_weekdays = weekdays.each_with_object({}).next
  #=> [["Monday", 2], {}]
item
  #=> ["Monday", 2] 
hash_weekdays
  #=> {} 

Ruby方式是以稍微复杂的方式使用并行赋值:

weekdays.each_with_object({}) { |(day, nbr), hash_weekdays|
  hash_weekdays[day] = nbr }
  #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5} 

正如其他人所说,最直接的答案是使用方法Hash::[]或(在v2.0中引入)Array#to_h

Hash[weekdays]
  #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}

Hash[*weekdays.flatten] #=> Hash["Monday", 2, "Tuesday", 4, "Thursday", 5] 
  #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}

weekdays.to_h
  #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}