【问题标题】:Convert string into Hashes of symbol and integer in Ruby在Ruby中将字符串转换为符号和整数的哈希
【发布时间】:2016-10-06 04:34:39
【问题描述】:

我想将这种格式的任何给定字符串:a = "a=2, b=3, c=4, d=5" 转换为符号(键)和整数(值)的哈希。

在这种情况下,预期的输入是{:a=>2, :b=>3, :c=>4, :d=>5}

这就是我所拥有的:

def hash_it(str)
  str.split(", ").map{|s| s.split("=")}.to_h
end

hash_it(str) 返回{"a"=>"2", "b"=>"3", "c"=>"4", "d"=>"5"}。关闭,但不完全。我不确定如何将键转换为符号,将值转换为整数。我可以分别转换它们:

str.split(", ").map{|s| s.split("=")}.map{|n| n[0].to_sym}
#=> [:a, :b, :c, :d]
str.split(", ").map{|s| s.split("=")}.map{|n| n[1].to_i}
#=> [2, 3, 4, 5]

但我无法将它们组合在一起以达到预期目的。

如何将"a=2, b=3, c=4, d=5" 格式的任何给定字符串转换为符号间键值{:a=>2, :b=>3, :c=>4, :d=>5} 的哈希?

【问题讨论】:

  • 也许值得注意的是,如果a 是您的数组,eval "{ #{a.gsub(/\w+/,':\1') } }" #=> {:a=>2, :b=>3, :c=>4, :d=>5}

标签: ruby hash


【解决方案1】:

我可能会这样做:

str = "a=2, b=3, c=4, d=5"
str.scan(/(\w+)=(\d+)/).map {|k,v| [ k.to_sym, v.to_i ] }.to_h

scan 只是提取每个键值对,其余的应该是不言自明的。

【讨论】:

  • 实际上认为某些正则表达式在这里会更好用
  • 虽然scan 是一个很棒的工具,但它也假设您的数据是原始的。输入中的任何垃圾都会被忽略,这可能是期望的行为或真正的问题。只是一个警告。
  • @tadman 当然可以。鉴于 OP 提供的信息很少,此处发布的所有解决方案都是如此 - 以及我们可以提出的任何解决方案。例如,如果= 两侧有意外的空白,我的解决方案可能会失败;使用 split 的解决方案可能会因意外的尾随或重复分隔符而失败。
【解决方案2】:

你离得太近了!以下将稍微修复/扩展您的尝试:

a = "a=2, b=3, c=4, d=5"

def hash_it(str)
  str.split(", ").map{|s| s.split("=")}.map{|n| [n[0].to_sym, n[1].to_i]}.to_h
end

hash_it(a) #=> {:a=>2, :b=>3, :c=>4, :d=>5}

【讨论】:

  • 不需要syms = 部分,因为这是一个单行。
【解决方案3】:

试试这个

String.class_eval do 
  def hashing
      self.split("#{oper1}").map{|s| [ s.split("#{oper2}")[0].strip.to_sym,s.split("#{oper2}")[1].to_i]}.to_h
  end
end

“你的字符串”.hash 如果你想让它使用“,=”作为默认值,其他地方的其他人这样做

String.class_eval do 
  def hashing(oper1= ',', oper2= '=')
     self.split(oper1.to_s).map{|s| [ s.split(oper2.to_s)[0].strip.to_sym,s.split(oper2.to_s)[1].to_i]}.to_h
  end
end

"YOUR STRING ".hashing
#or 
"ANOTHER SRTING".hashing("|", "!") # for another split operators.

希望对你有帮助。

【讨论】:

  • 这里的盲目rescue 声明是非常糟糕的形式,它抑制了错误并且没有提供很多帮助。您希望该代码生成哪些异常?
  • 什么是"#{oper1}"?您是否试图预测非字符串参数?如果没有,这完全没有意义,你应该使用oper1。如果是这样,为什么不直接做oper1.to_s
【解决方案4】:
def hashify(str)
  str.strip.split(/\s*(?:=|,\s)\s*/).each_slice(2).map { |k,v| [k.to_sym, v.to_i] }.to_h
end

str = " a = 2, b=3 , c= 4, d =5 "
hashify str
  #=> {:a=>"2", :b=>"3", :c=>"4", :d=>"5"}

split 操作显示为“在等号或逗号后跟空格以及任何周围的空白符处拆分”。

步骤如下。

s = str.strip
  #=> "a = 2, b=3 , c= 4, d =5"
a = s.split(/\s*(?:=|,\s)\s*/)
  #=> ["a", "2", "b", "3", "c", "4", "d", "5"] 
e = a.each_slice(2)
  #=> #<Enumerator: ["a", "2", "b", "3", "c", "4", "d", "5"]:each_slice(2)> 

我们可以通过将这个枚举器转换为数组来查看将生成的值。

e.to_a
  #=> [["a", "2"], ["b", "3"], ["c", "4"], ["d", "5"]] 

继续,

f = e.map { |k,v| [k.to_sym, v.to_i] }
  #=> [[:a, 2], [:b, 3], [:c, 4], [:d, 5]] 
f.to_h
  #=> {:a=>2, :b=>3, :c=>4, :d=>5}

【讨论】:

  • 我相信 OP 希望哈希值是数字。
  • 谢谢,@sagarpandya82。会修复的。
猜你喜欢
  • 2014-03-20
  • 2010-11-05
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
  • 2013-07-06
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多