Dołącz parę klucz / wartość do skrótu za pomocą znaku << w Rubim


80

W Rubim można dodawać wartości do istniejących tablic używając <<:

a = []
a << "foo"

ale czy możesz również dołączyć pary klucz / wartość do istniejącego skrótu?

h = {}
h << :key "bar"

Wiem, że potrafisz:

h[:key] = ""
h[:key] << "bar"

ale tego nie chcę.

Dzięki.


21
Dlaczego nie h[:key] = "bar"?
Hauleth

4
To nie działa:h[:key] << "bar"
Chris Nielsen,

Odpowiedzi:


141

Jest merge!.

h = {}
h.merge!(key: "bar")
# => {:key=>"bar"}

3
Nie sądzę, aby merge!kwalifikowało się to jako zwykłe utworzenie nowej pary klucz / wartość, ponieważ jest ona faktycznie używana do innego celu.
PericlesTheo

Słuszna uwaga. Myślę, że może to również skończyć się w zależności od innych czynników, których PO nie opublikował.
Michael Durrant

1
Ach, dzięki. Wygląda na to, że metoda sklepu działa podobnie. Było to głównie pytanie akademickie, ponieważ widziałem <<, o którym mówiłem, jako sposób na dołączanie do tablic, ale chciałem sprawdzić, czy działa to w przypadku skrótów. Dzięki jeszcze raz.
jcarpio

5
Różnica jest taka: storepo prostu dodaje nową parę, nie obchodzi go, czy klucz już istnieje. ze merge!jednak wpisy z zduplikowane klucze są zastępowane więc metoda robi nieco więcej niż tylko dodanie par. Jeśli porównasz te dwa, okaże storesię , że jesteś szybszy (trywialne, ale szczególnie w przypadku małych haszów)
PericlesTheo

2
@jcarpio Thanks. Hash#merge!zwraca wartość skrótu odbiornika, tak jak Array#<<zwraca tablicę odbiornika. Hash#storeto zupełnie inna sprawa. Ponadto, z cukrem składni mieszania key: "bar"w pozycji argumentu, pomyślałem, że jest to najbliższe możliwe do uzyskania notacji. Wiedziałem, że ten jest bliżej tego, czego chciałeś.
sawa

89

Ponieważ skróty nie są z natury uporządkowane, nie istnieje pojęcie dołączania. Jednak skróty Ruby od wersji 1.9 utrzymują kolejność reklam. Oto sposoby dodawania nowych par klucz / wartość.

Najprostszym rozwiązaniem jest

h[:key] = "bar"

Jeśli chcesz metodę, użyj store:

h.store(:key, "bar")

Jeśli naprawdę chcesz użyć operatora „łopata” ( <<), w rzeczywistości jest on dołączany do wartości skrótu jako tablica i musisz określić klucz:

h[:key] << "bar"

Powyższe działa tylko wtedy, gdy istnieje klucz. Aby dołączyć nowy klucz, musisz zainicjować skrót wartością domyślną, co możesz zrobić w następujący sposób:

h = Hash.new {|h, k| h[k] = ''}
h[:key] << "bar"

Możesz ulec pokusie, aby małpa łatać Hash, aby dołączyć operatora łopaty, który działa w sposób, w jaki napisałeś:

class Hash
  def <<(k,v)
    self.store(k,v)
  end
end

Jednak to nie dziedziczy „cukru syntaktycznego” stosowanego do operatora łopaty w innych kontekstach:

h << :key, "bar" #doesn't work
h.<< :key, "bar" #works

Dokładny! Dzięki za wkład i wgląd.
jcarpio

Należy zauważyć, że od Ruby 1.9 skróty są uporządkowane.
stal

1
Ruby 1.9+ utrzymuje kolejność wstawiania, ale Hash jako struktura danych nie ma pojęcia żadnego rodzaju wrodzonej kolejności.
Mark Thomas

27

Nie, nie sądzę, aby można było dołączać pary klucz / wartość. Jedyne, co jest mi najbliższe , to użycie storemetody:

h = {}
h.store("key", "value")

3

Może chcesz Hash # merge?

1.9.3p194 :015 > h={}
 => {} 
1.9.3p194 :016 > h.merge(:key => 'bar')
 => {:key=>"bar"} 
1.9.3p194 :017 > 

Jeśli chcesz zmienić tablicę w miejscu, użyj merge!

1.9.3p194 :016 > h.merge!(:key => 'bar')
 => {:key=>"bar"} 

Myślę, że mergeto nie jest dobry pomysł, ponieważ zwraca nową tablicę; nie dodawanie nowej pary do istniejącego skrótu.
PericlesTheo

A co z merge!(tj. Do istniejącej tablicy) zamiast merge?
Michael Durrant

1
merge!technicznie działa w tym kontekście, ale myślę, że powinien być używany do łączenia dwóch skrótów, a nie po prostu dodawania nowej pary. Ponadto, jeśli porównasz merge!, jest wolniej niż store;)
PericlesTheo

3

Są podobne merge!i storetraktują istniejące skróty w różny sposób w zależności od nazw kluczy, dlatego wpłyną na twoje preferencje. Inne niż to, z punktu widzenia składni, merge!„s key: "value"składnia zbliżony przeciwko JavaScript i Python. Osobiście zawsze nienawidziłem par klucz-wartość oddzielających przecinki.

hash = {}
hash.merge!(key: "value")
hash.merge!(:key => "value")
puts hash

{:key=>"value"}

hash = {}
hash.store(:key, "value")
hash.store("key", "value")
puts hash

{:key=>"value", "key"=>"value"}

Aby operator łopaty <<działał, radziłbym skorzystać z odpowiedzi Marka Thomasa .


1

Musiałem zrobić podobną rzecz, ale musiałem dodać wartości z tymi samymi kluczami. Kiedy używam scalania lub aktualizacji, nie mogę wypychać wartości za pomocą tych samych kluczy. Musiałem więc użyć tablicy skrótów.

    my_hash_static = {:header =>{:company => 'xx', :usercode => 'xx', :password => 'xx',
                      :type=> 'n:n', :msgheader => from}, :body=>[]}
    my_hash_dynamic = {:mp=>{:msg=>message, :no=>phones} }        
    my_hash_full = my_hash_static[:body].push my_hash_dynamic
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.