/ / Czym różni się `gsub` od` gsub! `, Gdy używasz skrótu jako wzorców do zastąpienia jego wartości? [zamknięte] - ruby, regex, hash

W jaki sposób `gsub` różni się od` gsub! `, Gdy używasz klawisza skrótu jako wzorca, aby zastąpić jego wartości? [zamknięte] - ruby, regex, hash

użyłem gsub! zastąpić dopasowanie hash kluczem z jego wartością hash. Na przykład:

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

wyjścia:

  1. TimeDateHello
  2. TimeDateHello

Nie rozumiem dlaczego gsub! zastępował wszystkie klucze skrótu za jednym razem, a nie przy każdej iteracji. Kiedy próbuję użyć gsub, zastępuje każdą iteracją:

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

Czy ktoś może wyjaśnić, dlaczego tak się dzieje?

Odpowiedzi:

1 dla odpowiedzi № 1

W tym względzie nie ma różnicy. The each Pętla jest wykonywana element po elemencie i żadna z nich gsub ani gsub! mogę przewidzieć przyszłość.

Ten kod:

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

jest równa:

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

z gsub! możesz napisać:

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

Główna różnica polega na tym gsub! zmienia odbiornik w miejscu, podczas gdy gsub zwraca nowy ciąg znaków (stąd konieczność przypisania go z powrotem string).

Aby wykonać wiele zamian jednocześnie, możesz przekazać skrót do gsub:

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

Wyrażenie regularne można również wygenerować programowo:

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

0 dla odpowiedzi nr 2

Zmodyfikowałem Twój kod, aby działał jak pokazano poniżej:

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

Za pomocą tego kodu gsub Dostaję:

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

i z gsub! Dostaję:

Time@ReplaceMe[123]@Hello
TimeDateHello

Przyczyna tego jest taka gsub! modyfikuje istniejący ciąg gdzie as gsub nie modyfikuje istniejącego ciągu. Czy to pomaga odpowiedzieć na twoje pytanie?