【问题标题】:How to turn a string of keys and values into a Ruby hash?如何将一串键和值转换为 Ruby 哈希?
【发布时间】:2015-02-12 08:52:23
【问题描述】:

我有一个包含键和值的字符串:

original = 'key1="value1" key2="value2"'

我已经开始分割空格:

items = original.split
=> ['key1="value1"', 'key2="value2"']

但现在我一直在努力寻找一种干净的方法将其转换为哈希。如何轻松地将这个原始的键和值字符串转换为键和值的哈希?

【问题讨论】:

  • 键是"key1""key2",还是变量key1key2的值?值是"value1""value2" 还是"\"value1\"""\"value2\""
  • 值应该是value1 而不是"value1"
  • 我编辑了我的答案以处理多余的引号。基本上,您只需将 .tr('"','') 添加到原始文件中即可。

标签: ruby


【解决方案1】:

如果您可以假设值周围的引号是适当平衡的,并且值中永远不会有转义的引号,那么使用正则表达式很容易:

Hash[*'key1="value1" key2="value2"'.scan(/(\b.*?)=(".*?")/).flatten]
# => {"key1"=>"\"value1\"", "key2"=>"\"value2\""}

或者在 Ruby 2.2 中:

'key1="value1" key2="value2"'.scan(/(\b.*?)=(".*?")/).to_h

否则,如果您只想在 = 上进行拆分,则值中将永远不会有空格:

'key1="value1" key2="value2"'.split.map {|pair| pair.split "=", 2 }.to_h

如果值中可能包含空格,那么您实际上需要编写一个有状态的解析器。

【讨论】:

    【解决方案2】:
    Hash[original.split.collect {|i| i.split('=')}]
    

    首先,split 为您提供一个包含每个 key="value" 的数组:

    > original.split
    => ["key1=\"value1\"", "key2=\"value2\""]
    

    然后,collect + split 将每个key="value" 子数组变成[key,value] 的数组:

    > original.split.collect {|i| i.split('=')}
    => [["key1", "\"value1\""], ["key2", "\"value2\""]]
    

    最后,传递给 Hash 构造函数:

    > Hash[original.split.collect {|i| i.split('=')}]
    => {"key2"=>"\"value2\"", "key1"=>"\"value1\""}
    

    【讨论】:

    • 它会起作用,但你的*flatten 是多余的。
    • 不...如果没有flatten,您会得到不同的结果。您得到的是{["key1", '"value1"'] => ["key2", '"value2"']},而不是所需的输出——也就是说,第一个键/值作为新哈希的键,下一个键/值作为新哈希的值。
    • 我并不打算将它们中的每一个单独分开。我说他们在一起是多余的。
    • 啊……是的,是的。非常感谢!
    • 这很接近,但它仍然需要删除值字符串周围的双引号。结果应该是{"key1"=>"value1"} 而不是{"key1"=>"\"value1\""}
    【解决方案3】:
    items_hash = original.tr('"','').split.collect {|i| i.split('=')}.to_h
    

    【讨论】:

    • .to_h 不是 Ruby
    • @dgilperez 我不知道你是不是在做梦。 to_h 是一个数组方法。
    • @dgilperez 它在 Ruby 2.2+ 中。
    • 致后来该线程的所有读者:dgilperez 的原始评论并没有说明它现在所说的内容。它说“.to_h 不是数组定义的方法。”此外,dgilperez 不知何故否决了这个答案,然后撤回。
    • 这将返回 {"key1"=>"\"value1\"", "key2"=>"\"value2\""} 。关于键是否为字符串的问题尚不清楚,但我希望值是"value1""value2"
    【解决方案4】:

    这个位怎么样:

    original.split.each_with_object({}) do |el, h| 
       parts = el.split("=")
       h[parts.first] = parts.last.gsub("\"", '') 
    end
    
    => {
      "key1" => "value1",
      "key2" => "value2"
    }
    

    我建议你看看Enumerable 模块,这里使用的是each_with_objecthttp://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-each_with_object

    【讨论】:

    • 不知道为什么要投反对票...我会给你投赞成票,因为它有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2016-08-14
    • 2010-10-18
    • 1970-01-01
    • 2010-12-16
    • 2011-12-19
    • 2016-02-05
    相关资源
    最近更新 更多