使用值交换哈希键并将键转换为Ruby中的符号?

时间:2014-04-09 23:18:00

标签: ruby loops hash

这是输入哈希:

p Score.periods #{"q1"=>0, "q2"=>1, "q3"=>2, "q4"=>3, "h1"=>4, "h2"=>5}

这是我当前使用值交换密钥的代码,同时将密钥转换为符号:

periods = Score.periods.inject({}) do |hsh,(k,v)|
  hsh[v] = k.to_sym
  hsh
end

结果如下:

p periods #{0=>:q1, 1=>:q2, 2=>:q3, 3=>:q4, 4=>:h1, 5=>:h2}

看起来我的代码看起来很笨重,不应该用4行来做我在这里做的事情。是否有更清晰的方式来写这个?

3 个答案:

答案 0 :(得分:3)

你可以这样做:

Hash[periods.values.zip(periods.keys.map(&:to_sym))]

或者,如果您使用的是版本为to_h可用于阵列的Ruby版本,则可以执行以下操作:

periods.values.zip(periods.keys.map(&:to_sym)).to_h

上面两个例子的作用是创建原始哈希的键和值的数组。请注意,通过将to_sym传递给map作为Proc来将哈希的字符串键映射到符号:

periods.keys.map(&:to_sym)
# => [:q1, :q2, :q3, :q4, :h1, :h2]

periods.values
# => [0, 1, 2, 3, 4, 5]

然后将它们压缩成[value, key]对数组,其中values的每个对应元素与keys中的相应键匹配:

periods.values.zip(periods.keys.map(&:to_sym))
# => [[0, :q1], [1, :q2], [2, :q3], [3, :q4], [4, :h1], [5, :h2]]

然后可以使用Hash[array]array.to_h将该数组转换回哈希值。

答案 1 :(得分:3)

最简单的方法是:

data = {"q1"=>0, "q2"=>1, "q3"=>2, "q4"=>3, "h1"=>4, "h2"=>5}

Hash[data.invert.collect { |k, v| [ k, v.to_sym ] }]

Hash[]方法将键/值对数组转换为实际的哈希值。对于这样的情况非常方便。

如果你正在使用Ruby on Rails,这可能会更容易:

data.symbolize_keys.invert

答案 2 :(得分:2)

h = {"q1"=>0, "q2"=>1, "q3"=>2, "q4"=>3, "h1"=>4, "h2"=>5}

h.each_with_object({}) { |(k,v),g| g[v] = k.to_sym  }
  #=> {0=>:q1, 1=>:q2, 2=>:q3, 3=>:q4, 4=>:h1, 5=>:h2} 

步骤如下(为了Ruby新手的利益)。

enum = h.each_with_object({})
  #=> #<Enumerator: {0=>"q1", 1=>"q2", 2=>"q3", 3=>"q4",
  #                  4=>"h1", 5=>"h2"}:each_with_object({})>

通过使用Enumerable#entriesEnumerable#to_a将枚举数转换为数组,可以看到枚举器生成并传递给块的元素。

enum.entries
  #=> [[["q1", 0], {}], [["q2", 1], {}], [["q3", 2], {}],
  #    [["q4", 3], {}], [["h1", 4], {}], [["h2", 5], {}]] 

继续,

enum.each { |(k,v),g| g[v] = k.to_sym  }
  #=> {0=>:q1, 1=>:q2, 2=>:q3, 3=>:q4, 4=>:h1, 5=>:h2}

在最后一步中,Enumerator#eachenum生成的第一个元素传递给块并分配三个块变量。考虑传递给块的enum的第一个元素以及三个块变量的值的关联计算。 (我必须首先执行enum.rewind重新初始化enum,因为上面的each将调查员结束。请参阅Enumerator#rewind)。

(k, v), g = enum.next
  #=> [["q1", 0], {}]
k #=> "q1"
v #=> 0
g #=> {}

Enumerator#next。因此块计算

g[v] = k.to_sym
  #=> :q1

因此,

g #=> {0=>:q1}

enum的下一个元素被传递给块并执行类似的计算。

(k, v), g = enum.next
  #=> [["q2", 1], {0=>:q1}] 
k #=> "q2" 
v #=> 1 
g #=> {0=>:q1} 
g[v] = k.to_sym
  #=> :q2 
g #=> {0=>:q1, 1=>:q2} 

其余的计算方法类似。