Ruby: łączenie zmiennych w łańcuch

95

Szukam lepszego sposobu na scalanie zmiennych w łańcuch w Rubim.

Na przykład, jeśli ciąg jest podobny do:

„Theanimal actionsecond_animal "

I mam dla zmiennych animal, actioni second_animalto, co jest preferowanym sposobem na wprowadzenie tych zmiennych w na ciąg?

FearMediocrity
źródło

Odpowiedzi:

240

Idiomatycznym sposobem jest napisanie czegoś takiego:

"The #{animal} #{action} the #{second_animal}"

Zwróć uwagę na podwójne cudzysłowy (") otaczające ciąg: to jest wyzwalacz dla Rubiego, aby użył wbudowanego zastępowania znaków zastępczych. Nie możesz ich zastąpić pojedynczymi cudzysłowami (') lub ciąg zostanie zachowany bez zmian.

Mike Woodhouse
źródło
2
Przepraszam, może za bardzo uprościłem problem. Ciąg zostanie pobrany z bazy danych, a zmienna zależy od wielu czynników. Zwykle użyłbym zamiany na 1 lub dwie zmienne, ale może to być więcej. jakieś pomysły?
FearMediocrity
Konstrukcja # {} jest prawdopodobnie najszybsza (chociaż nadal wydaje mi się to sprzeczne z intuicją). Oprócz sugestii gixa, możesz również łączyć łańcuchy z + lub <<, ale mogą zostać utworzone pewne ciągi pośrednie, co jest kosztowne.
Mike Woodhouse
Najlepszy sposób na interpolację zmiennych
Dragutescu Alexandru
115

Możesz użyć formatowania podobnego do sprintf, aby wstrzyknąć wartości do ciągu. W tym celu ciąg musi zawierać symbole zastępcze. Umieść swoje argumenty w tablicy i użyj jednego z następujących sposobów: (Aby uzyskać więcej informacji, zajrzyj do dokumentacji Kernel :: sprintf .)

fmt = 'The %s %s the %s'
res = fmt % [animal, action, other_animal]  # using %-operator
res = sprintf(fmt, animal, action, other_animal)  # call Kernel.sprintf

Możesz nawet jawnie określić numer argumentu i przetasować go wokół:

'The %3$s %2$s the %1$s' % ['cat', 'eats', 'mouse']

Lub określ argument za pomocą kluczy z krzyżykiem:

'The %{animal} %{action} the %{second_animal}' %
  { :animal => 'cat', :action=> 'eats', :second_animal => 'mouse'}

Zauważ, że musisz podać wartość dla wszystkich argumentów dla %operatora. Na przykład nie możesz uniknąć definiowania animal.

gix
źródło
18

Użyłbym #{}konstruktora, zgodnie z innymi odpowiedziami. Chcę również zwrócić uwagę, że jest tu prawdziwa subtelność, na którą należy uważać:

2.0.0p247 :001 > first_name = 'jim'
 => "jim" 
2.0.0p247 :002 > second_name = 'bob'
 => "bob" 
2.0.0p247 :003 > full_name = '#{first_name} #{second_name}'
 => "\#{first_name} \#{second_name}" # not what we expected, expected "jim bob"
2.0.0p247 :004 > full_name = "#{first_name} #{second_name}"
 => "jim bob" #correct, what we expected

Natomiast łańcuchy mogą być tworzone z apostrofami (o czym świadczy first_namei last_namezmiennych, konstruktor może być stosowany wyłącznie w ciągach o cudzysłowach.#{}

Starkers
źródło
13
["The", animal, action, "the", second_animal].join(" ")

to inny sposób na zrobienie tego.

Andrew Grimm
źródło
10

Nazywa się to interpolacją ciągów i robisz to w następujący sposób:

"The #{animal} #{action} the #{second_animal}"

Ważne: zadziała tylko wtedy, gdy ciąg znaków znajduje się w cudzysłowie („”).

Przykład kodu, który nie będzie działał zgodnie z oczekiwaniami:

'The #{animal} #{action} the #{second_animal}'
sqrcompass
źródło
Dziękujemy za użycie właściwego terminu, aby nowi programiści mogli się nauczyć: interpolacja.
Mike Bethany
3

Standardowy system szablonów ERB może działać w Twoim scenariuszu.

def merge_into_string(animal, second_animal, action)
  template = 'The <%=animal%> <%=action%> the <%=second_animal%>'
  ERB.new(template).result(binding)
end

merge_into_string('tiger', 'deer', 'eats')
=> "The tiger eats the deer"

merge_into_string('bird', 'worm', 'finds')
=> "The bird finds the worm"
Clint Pachl
źródło
0

Możesz go używać ze zmiennymi lokalnymi, na przykład:

@animal = "Dog"
@action = "licks"
@second_animal = "Bird"

"The #{@animal} #{@action} the #{@second_animal}"

wyjście byłoby: „The Pies liże Ptak

Níkolas La Porta
źródło