Kaip pašalinti raktą iš Hash ir gauti likusią maišą Ruby / Rails?

Jei norite pridėti naują porą „Hash“, aš:

 {:a => 1, :b => 2}.merge!({:c => 3}) #=> {:a => 1, :b => 2, :c => 3} 

Ar yra panašus būdas ištrinti raktą iš „Hash“?

Jis veikia:

 {:a => 1, :b => 2}.reject! { |k| k == :a } #=> {:b => 2} 

bet aš tikiuosi kažką panašaus:

 {:a => 1, :b => 2}.delete!(:a) #=> {:b => 2} 

Svarbu, kad grąžinimo vertė būtų likusi maišos vertė, kad galėčiau padaryti tokius dalykus:

 foo(my_hash.reject! { |k| k == my_key }) 

vienoje eilutėje.

404
03 июня '11 в 16:19 2011-06-03 16:19 nustatė Misha Moroshko birželio 03 d. 11 val. 16:19 2011-06-03 16:19
@ 12 atsakymų

Bėgiai turi išimtį / išimtį! metodas, kuris grąžina maišą su nuotoliniais mygtukais. Jei jau naudojate „Rails“, nėra prasmės sukurti savo versiją.

 class Hash # Returns a hash that includes everything but the given keys. # hash = { a: true, b: false, c: nil} # hash.except(:c) # => { a: true, b: false} # hash # => { a: true, b: false, c: nil} # # This is useful for limiting a set of parameters to everything but a few known toggles: # @person.update(params[:person].except(:admin)) def except(*keys) dup.except!(*keys) end # Replaces the hash without the given keys. # hash = { a: true, b: false, c: nil} # hash.except!(:c) # => { a: true, b: false} # hash # => { a: true, b: false } def except!(*keys) keys.each { |key| delete(key) } self end end 
569
19 июня '12 в 20:03 2012-06-19 20:03 atsakymą pateikė Peter Brownas birželio 19 d. 12 val. 20:03 2012-06-19 20:03

Oneliner paprastas rubinas, jis veikia tik su rubinu> 1.9.x:

 1.9.3p0 :002 > h = {:a => 1, :b => 2} => {:a=>1, :b=>2} 1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) } => {:b=>2} 

Bakstelėjimo metodas visada grąžina pavadinimą ...

Priešingu atveju, jei jums reikia active_support/core_ext/hash (kuri automatiškai reikalinga kiekvienoje „Rails“ programoje), galite naudoti vieną iš šių būdų, priklausomai nuo jūsų poreikių:

 ➜ ~ irb 1.9.3p125 :001 > require 'active_support/core_ext/hash' => true 1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3} => {:a=>1, :b=>2, :c=>3} 1.9.3p125 :003 > h.except(:a) => {:b=>2, :c=>3} 1.9.3p125 :004 > h.slice(:a) => {:a=>1} 

išskyrus naudoja juodąjį sąrašą, todėl jis pašalina visus raktus, nurodytus kaip argumentus, ir gabalas naudoja baltąjį sąrašą, todėl pašalina visus raktus, kurie nėra nurodyti kaip argumentai. Taip pat yra šio metodo sprogimo versija ( except! Ir slice! ) Tai keičia šią maišą, tačiau jų grįžimo vertė yra kitokia, o abi jos grąžina maišą. Jame rodomi nuotoliniai klavišai slice! ir raktai, kurie yra saugomi, except! :

 1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a) => {:b=>2, :c=>3} 1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a) => {:b=>2, :c=>3} 
159
27 янв. Atsakymą pateikė Fabio sausio 27 d. 2012-01-27 03:35 '12 at 3:35 2012-01-27 03:35

Kodėl gi ne naudoti:

 hash.delete(key) 
126
03 июня '11 в 16:23 2011-06-03 16:23 atsakymas duotas dbryson birželio 03 '11, 16:23 2011-06-03 16:23
 #in lib/core_extensions.rb class Hash #pass single or array of keys, which will be removed, returning the remaining hash def remove!(*keys) keys.each{|key| self.delete(key) } self end #non-destructive version def remove(*keys) self.dup.remove!(*keys) end end #in config/initializers/app_environment.rb (or anywhere in config/initializers) require 'core_extensions' 

Aš ją įdiegiau taip, kad .remove grąžina maišos kopiją su ištaisytais klavišais ir ištrinti! keičia maišelį. Tai atitinka rubino konvencijas. pavyzdžiui, iš konsolės

 >> hash = {:a => 1, :b => 2} => {:b=>2, :a=>1} >> hash.remove(:a) => {:b=>2} >> hash => {:b=>2, :a=>1} >> hash.remove!(:a) => {:b=>2} >> hash => {:b=>2} >> hash.remove!(:a, :b) => {} 
30
03 июня '11 в 17:42 2011-06-03 17:42 atsakymas pateikiamas max williams birželio 03 '11, 17:42 pm 2011-06-03 17:42

Yra daug būdų pašalinti raktą iš maišos ir gauti likusią maišą Ruby.

  • .slice => Jis grąžins pasirinktus raktus ir nepašalins jų iš šaltinio maišos

     2.2.2 :074 > hash = {"one"=>1, "two"=>2, "three"=>3} => {"one"=>1, "two"=>2, "three"=>3} 2.2.2 :075 > hash.slice("one","two") => {"one"=>1, "two"=>2} 2.2.2 :076 > hash => {"one"=>1, "two"=>2, "three"=>3} 
  • .delete => Jis ištrins pasirinktus raktus iš šaltinio maišos (jis gali priimti tik vieną raktą ir ne daugiau kaip vieną)

     2.2.2 :094 > hash = {"one"=>1, "two"=>2, "three"=>3} => {"one"=>1, "two"=>2, "three"=>3} 2.2.2 :095 > hash.delete("one") => 1 2.2.2 :096 > hash => {"two"=>2, "three"=>3} 
  • .except => Jis grąžins likusius klavišus, bet neištrins nieko iš šaltinio maišos

     2.2.2 :097 > hash = {"one"=>1, "two"=>2, "three"=>3} => {"one"=>1, "two"=>2, "three"=>3} 2.2.2 :098 > hash.except("one","two") => {"three"=>3} 2.2.2 :099 > hash => {"one"=>1, "two"=>2, "three"=>3} 
  • .delete_if => Jei reikia ištrinti raktą pagal vertę. Tai akivaizdžiai pašalins atitinkamus raktus iš šaltinio maišos.

     2.2.2 :115 > hash = {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1} => {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1} 2.2.2 :116 > value = 1 => 1 2.2.2 :117 > hash.delete_if { |k,v| v == value } => {"two"=>2, "three"=>3} 2.2.2 :118 > hash => {"two"=>2, "three"=>3} 

Rezultatai, pagrįsti Ruby 2.2.2.

29
30 авг. techdreams atsakymas rugpjūčio 30 d 2016-08-30 18:05 '16 at 18:05 pm 2016-08-30 18:05

Jei norite naudoti gryną „Ruby“ (be bėgių), nenorite sukurti plėtinių metodų (jums gali prireikti tik vienoje ar dviejose vietose ir nenorite užteršti vardų erdvės įvairiais būdais), kuriuos norite redaguoti vietoje (t. E. Jūs esate funkcinio programavimo, pvz., Man, gerbėjas, galite pasirinkti:

 >> x = {:a => 1, :b => 2, :c => 3} => {:a=>1, :b=>2, :c=>3} >> x.select{|x| x != :a} => {:b=>2, :c=>3} >> x.select{|x| ![:a, :b].include?(x)} => {:c=>3} >> x => {:a=>1, :b=>2, :c=>3} 
29
19 дек. Atsakymą pateikė Yura Taras gruodžio 19 d. 2012-12-19 16:55 '12 at 16:55 2012-12-19 16:55

Galite naudoti, except! brangakmenių facets :

 >> require 'facets' # or require 'facets/hash/except' => true >> {:a => 1, :b => 2}.except(:a) => {:b=>2} 

Originalus maišos nesikeičia.

EDIT: Kaip sako Russell, veidai turi tam tikrų paslėptų problemų ir nėra visiškai suderinami su API su „ActiveSupport“. Kita vertus, „ActiveSupport“ nėra tokia išsami, kaip ribos. Galiausiai norėčiau naudoti AS ir padaryti klaidas jūsų kode.

26
13 окт. duotas atsakymas perrašytas spalio 13 d. 2011-10-13 03:25 '11 at 3:25 2011-10-13 03:25

Užuot naudoję beždžionę arba nereikia įtraukti didelių bibliotekų, galite naudoti patobulinimus, jei naudojate Ruby 2 :

 module HashExtensions refine Hash do def except!(*candidates) candidates.each { |candidate| delete(candidate) } self end def except(*candidates) dup.remove!(candidates) end end end 

Šią funkciją galite naudoti nedarant įtakos kitoms programos dalims arba turėti didelių išorinių bibliotekų.

 class FabulousCode using HashExtensions def incredible_stuff delightful_hash.except(:not_fabulous_key) end end 
17
12 дек. Atsakymą pateikė Mohamad 12 Dec 2014-12-12 22:19 '14, 22:19 2014-12-12 22:19

gryno rubino:

 {:a => 1, :b => 2}.tap{|x| x.delete(:a)} # => {:b=>2} 
13
07 сент. atsakymas, kurį pateikė gamov 07 Sep 2012-09-07 07:25 '12 at 7:25 2012-09-07 07:25

Žr. „ Ruby on Rails“: ištrinkite kelis maišos raktus.

 hash.delete_if{ |k,| keys_to_delete.include? k } 
10
07 апр. atsakymą pateikė Nakilon 07 balandžio. 2014-04-07 07:18 '14 at 7:18 2014-04-07 07:18

Tai yra viena eilutė, kaip tai padaryti, tačiau ji nėra labai suprantama. Vietoj to rekomenduojamos dvi eilutės.

 use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call) 
1
12 янв. atsakymas, kurį pateikė the_minted Jan 12 2014-01-12 18:33 '14 at 18:33 2014-01-12 18:33

Jis taip pat veikia: hash[hey] = nil

-6
02 февр. atsakymas pateikiamas fdghdfg 02 Feb. 2014-02-02 22:29 '14, 22:29 2014-02-02 22:29