【问题标题】:Parsing a string list with multiple values into JSON将具有多个值的字符串列表解析为 JSON
【发布时间】:2020-03-28 15:49:04
【问题描述】:

我有大约三万条记录,其中一个字符串列以以下格式存储,具有不同的键:

"something: this, this and that, that, other stuff, another: name, another name, last: here"

在 Rails 中,我想将其更改为类似的哈希

{
    something: [ "this", "this and that", "that" ],
    another: [ "name", "another name" ],
    last: [ "here" ]   
}

有没有办法优雅地做到这一点?我正在考虑在冒号处拆分,然后对第一个空格进行反向搜索。

【问题讨论】:

  • 这应该让你开始string.scan(/[\w\s]+[:,]/).inspect

标签: ruby-on-rails json ruby parsing


【解决方案1】:

优雅地:

result_hash = {}

string.scan(/(?<key>[\w]+(?=:))|(?<value>[\s\w]+(?=(,|\z)))/) do |key,value|
  if key.present?
    result_hash[key] = []
    current_key = key
  elsif value.present?
    result_hash[current_key] << value.strip
  end
end

然后json化:

json = result_hash.to.json

【讨论】:

    【解决方案2】:

    大约有一百种方法可以解决这个问题。一个非常简单的方法是:

    str = "something: this, this and that, that, other stuff, another: name, another name, last: here"
    
    key = nil
    str.scan(/\s*([^,:]+)(:)?\s*/).each_with_object({}) do |(val, colon), hsh|
      if colon
        key = val.to_sym
        hsh[key] = []
      else
        hsh[key] << val
      end
    end
    # => {
    #      something: ["this", "this and that", "that", "other stuff"], 
    #      another: ["name", "another name"],
    #      last: ["here"]
    #    }
    

    它通过使用以下正则表达式扫描字符串来工作:

    /
      \s*      # any amount of optional whitespace
      ([^,:]+) # one or more characters that aren't , or : (capture 1)
      (:)?     # an optional trailing : (capture 2)
      \s*     # any amount of optional whitespace
    /x
    

    然后它遍历匹配项并将它们放入哈希中。当匹配有一个尾随冒号(捕获 2)时,将创建一个新的哈希键,其中包含一个空数组作为值。否则,值(捕获 1)将添加到最新键的数组中。

    或者……

    一种不太直接但更聪明的方法是让 RegExp 做更多的工作:

    MATCH_LIST_ENTRY = /([^:]+):\s*((?:[^,]+(?:,\s*|$))+?)(?=[^:,]+:|$)/
    
    def parse_list2(str)
      str.scan(MATCH_LIST_ENTRY).map do |k, vs|
        [k.to_sym, vs.split(/,\s*/)]
      end.to_h
    end
    

    我不会为这个选择正则表达式,但它比看起来更简单。 Regexper does a pretty good job 解释一下。

    您可以在 repl.it 上看到这两个操作:https://repl.it/@jrunning/LongtermMidnightblueAssembler

    【讨论】:

      【解决方案3】:

      如果str是示例中给出的字符串,则可以按如下方式构造所需的哈希。

      str.split(/, *(?=\p{L}+:)/).
          each_with_object({}) do |s,h|
            k, v = s.split(/: +/)
            h[k.to_sym]= v.split(/, */)
          end
        #=> {:something=>["this", "this and that", "that", "other stuff"],
        #    :another=>["name", "another name"],
        #    :last=>["here"]} 
      

      注意:

      str.split(/, *(?=\p{L}+:)/)
        #=> ["something: this, this and that, that, other stuff",
        #    "another: name, another name",
        #    "last: here"] 
      

      这个正则表达式的内容是,“匹配一个逗号后跟零个或多个空格,匹配后紧跟一个或多个 Unicode 字母后跟冒号,(?=\p{L}+:) 是一个正向预测 ”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 2020-08-13
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        相关资源
        最近更新 更多