【问题标题】:How does `gsub` differ from `gsub!` when using hash key as patterns to substitute its values? [closed]当使用哈希键作为模式替换其值时,`gsub` 与 `gsub!` 有何不同? [关闭]
【发布时间】:2016-04-16 04:16:11
【问题描述】:

我使用gsub! 将匹配项替换为带有哈希值的哈希键。例如:

def replace_string(string = "@ReplaceMe[xyz]@@ReplaceMe[123]@Hello")
  generator_replacements = {
    "@ReplaceMe[xyz]@" => "Time",
    "@ReplaceMe[123]@" => "Date"
  }
  generator_replacements.each{
    |generator, replacement|
    string = string.gsub!(generator.to_s, replacement.to_s)
    puts string
  }
end

replace_string

输出:

  1. TimeDateHello
  2. TimeDateHello

我不明白为什么gsub! 一次性替换所有哈希键,而不是每次迭代。当我尝试使用gsub 时,它会替换为每次迭代:

  1. Time@ReplaceMe[123]@Hello
  2. TimeDateHello

有人可以解释为什么会这样吗?

【问题讨论】:

  • 这不是有效的语法。您不要在 Ruby 中的方法定义周围使用花括号。 generated_string 是什么?我有一种感觉,这不是您的实际工作(或不工作)代码。请编辑您的问题以包含您的实际代码。
  • 你能想出一个使用不那么神秘的占位符名称的例子吗?
  • 什么是generated_string
  • @Jordan 这不是我的实际代码,正确。出于保密原因,我需要在此处发布之前删除任何实际变量名称和数据的痕迹。我现在已将 generated_string 更正为 string

标签: ruby regex hash


【解决方案1】:

我已经编辑了您的代码,使其如下所示:

def replace_string(generated_string = "@ReplaceMe[xyz]@@ReplaceMe[123]@Hello")
  generator_replacements = {
    "@ReplaceMe[xyz]@" => "Time",
    "@ReplaceMe[123]@" => "Date"
  }
  generator_replacements.each do |generator, replacement|
    string = generated_string.gsub(generator.to_s, replacement.to_s)
    puts string
  end
end

使用此代码使用gsub 我得到:

Time@ReplaceMe[123]@Hello
@ReplaceMe[xyz]@DateHello

gsub! 我得到:

Time@ReplaceMe[123]@Hello
TimeDateHello

原因是gsub! 修改了现有字符串,而gsub 不修改现有字符串。这有助于回答您的问题吗?

【讨论】:

    【解决方案2】:

    在这方面没有区别。 each 循环逐个元素执行,gsubgsub! 都无法预见未来。

    这段代码:

    replacements = { 'foo' => 'hello', 'bar' => 'world' }
    string = 'foo bar!'
    replacements.each do |placeholder, value|
      string = string.gsub(placeholder, value)
    end
    string #=> 'hello world!'
    

    相当于:

    string = 'foo bar!'
    string = string.gsub('foo', 'hello') #=> "hello bar!"
    string = string.gsub('bar', 'world') #=> "hello world!"
    string #=> 'hello world!'
    

    gsub! 你可以写:

    string = 'foo bar!'
    string.gsub!('foo', 'hello') #=> "hello bar!"
    string.gsub!('bar', 'world') #=> "hello world!"
    string #=> 'hello world!'
    

    主要区别在于gsub! 就地更改接收器,而gsub 返回一个新字符串(因此需要将其分配回string)。

    要一次执行多个替换,您可以将哈希传递给gsub

    string = 'foo bar!'
    string.gsub(/foo|bar/, { 'foo' => 'hello', 'bar' => 'world' })
    #=> "hello world!"
    

    也可以通过编程方式生成正则表达式:

    replacements = { 'foo' => 'hello', 'bar' => 'world' }
    string = 'foo bar!'
    string.gsub(Regexp.union(replacements.keys), replacements)
    #=> "hello world!"
    

    【讨论】:

    • 如果是这样,那gsubgsub!没有区别,只是gsub!覆盖了string,那为什么我的函数没有输出 Time@ReplaceMe[123]@Hello 然后 TimeDateHello?
    • @QCFia 请参阅Jordan's comment,您的代码无效,我们不知道您的方法是如何被调用的。请编辑您的问题并包含您的实际代码。
    • 现在更有意义了吗??
    • @QCFia 无论我使用gsub 还是gsub!,我都会得到相同的输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多