【问题标题】:remove last character from looping Hash从循环哈希中删除最后一个字符
【发布时间】:2021-10-09 06:59:11
【问题描述】:

你能帮我用这段代码解决这个问题吗?

total_user_input = []

while true
  print "Field Name: "
  user_input = gets.chomp
  break if user_input.empty?
  total_user_input << user_input
end


total_user_input.each do |input|
  aa = input.split(":").reduce {|first, second| "  \t'#{first}': '#{second}',\r\n".gsub("'",'"') }
  puts aa.chomp(',')
end

我得到的结果

"name": "string",
"desc": "string",
"price": "integer",

但我想要的只是删除最后一个逗号

"name": "string",
"desc": "string",
"price": "integer"

谢谢你帮助我

【问题讨论】:

  • 在您的示例中,total_user_input 是什么?注意each(这里是Array#each)总是返回它的接收者。在你的例子中是total_user_input
  • 你想生成 JSON 吗?
  • 是的,我正在尝试生成 json
  • Ruby 带有一个 JSON 库。它负责所有格式和转义。见Generating JSON
  • 我知道,但我只想从我的代码中删除最后一个逗号

标签: ruby ruby-2.0 ruby-3


【解决方案1】:

我不知道你的实际情况,但我根据你的预期,你可以试试。

total_user_input = [
  "name:test",
  "age:30"
]

input_length = total_user_input.size
total_user_input.each_with_index do |input, index|
  aa = input.split(":").reduce {|first, second| "  \t'#{first}': '#{second}',\r\n".gsub("'",'"') }
  aa = aa.gsub(',', '') if index == input_length - 1 # or aa.slice(-1)
  puts aa
end

=> 我的结果

"name": "test",
"age": "30"

【讨论】:

    【解决方案2】:

    TL;DR

    我很高兴回答您实际提出的问题,但需要指出的是,您所做的事情本质上是一种反模式,而不是惯用的 Ruby。

    我将首先向您展示一种更好的方法来做您正在做的事情,使用转换阶段而不是单一的惯用方法链。接下来,我将介绍一些替代方案,它们可以帮助您处理已经构建的字符串数据。

    最后,我还提供了一些您通常应该注意的警告,但对于回答您的问题并不是必不可少的。它们仍然很有用,并且在您尝试调试某些东西时肯定会帮助解决这些问题。

    正确的方法

    首先,如果可以避免的话,不要做你正在做的事情。以这种方式解决问题会导致非常脆弱的解决方案。相反,只需将您的输入对直接转换为 Hash 或 JSON。例如:

    require "json"
    
    pp total_user_input
    #=> ["name", "string", "desc", "string", "price", "integer"]
    
    aa = total_user_input.each_slice(2).to_h
    #=> {"name"=>"string", "desc"=>"string", "price"=>"integer"}
    
    puts JSON.pretty_generate aa
    
    {
      "name": "string",
      "desc": "string",
      "price": "integer"
    }
    

    这将分阶段转换您的输入,并将字符串打印到适合写入文件或以其他方式漂亮打印为 JSON 的 STDOUT。

    您的原始问题已得到解答

    如果您坚持尝试修改给定的字符串,我们将首先将其表示为 here-document。

    your_pseudo_json = <<~STRING
      "name": "string",
      "desc": "string",
      "price": "integer",
    STRING
    

    对于这个给定的字符串,您的选项有限。使用 Windows 样式的换行符而不是 Unix 样式的换行符也会使您的生活变得复杂,但您可以通过以下两种方式之一来处理:

    1. 为您的系统使用$/ record separator,可能默认定义,或自行设置。然后你可以使用 String#chomp。例如:

       # If you have to set it explicitly, do so by assigning to $/
       # NB: You may not. I don't have a Windows system to check.
       $/ = "\r\n"
      
       your_pseudo_json.chomp!(",#{$/}")
      
    2. 使用anchored regular expression 仅删除最后的项目。无论您的平台的行尾如何,这都将起作用。例如:

       your_pseudo_json.sub! /,(?:\r?\n)\z/, ""
      
    3. 如果您正在运行支持String#delete_suffix! 的较新的 Ruby,那么您几乎可以像 #chomp 一样执行此操作,但使用没有插值的简单字符串。例如:

       # for Windows line endings
       your_pseudo_json.delete_suffix! ",\r\n"
      
       # for *nix-style line endings
       your_pseudo_json.delete_suffix! ",\n"
      

    注意事项

    在 Irb 或 Pry 中使用非 Bang 方法进行测试

    作为测试说明,请在您的 REPL 中使用 #chomp、#sub 和 #delete_suffix 的非 bang 方法进行测试,这样您就不必在实验时不断重新创建字符串。 bang 方法将就地修改您的字符串,除非您在默认启用冻结字符串的情况下运行。

    冻结字符串

    另外,请注意,如果您在程序中使用了 freeze strings pragma,例如:

    • # frozen_string_literal: true 在 .rb 文件的顶部
    • RUBYOPT="--enable-frozen-string-literal" 调用你的 REPL 时在你的环境中

    然后使用非爆炸方法并将结果分配回不同(甚至相同)的变量。复制unfrozen copies of frozen strings 超出了您当前问题的范围,所以我什至不会提及它,除非防止其他读者对该主题的一般自行车脱落。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-18
      • 1970-01-01
      • 2018-11-22
      • 2013-02-17
      • 2021-12-13
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      相关资源
      最近更新 更多