2014-05-09 19 views
6

bazı tuşları görmezden Nasıl/kesişir/farkını sağlamalarının iki dizilerden örneğin:sağlamalarının iki dizilerden birlik/kesişir/farkını almak ve birliğe almak istiyorum

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}] 
array2 = [{:name =>'Guy1', :age => 45},{:name =>'Guy3', :age => 45}] 

...

p array1 - array2 

=> [{:name=>"Guy2", :age=>45}] 


p array2 - array1 
=> [{:name=>"Guy3", :age=>45}] 


p array1 | array2 
=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy3", :age=>45}] 

ancak sadece adlarına göre karşılaştırmak ve örneğin sağlamalarının bunları kaldırmak gerek kalmadan yaş görmezden istediğinizde:

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}] 
array2 = [{:name =>'Guy1', :age => 46},{:name =>'Guy3', :age => 45}] 

Bu durumda, yaşlarımın farklı olmasını istediğim sonuçları almıyorum.

array1 - array2 

=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}] 

array2 - array1 
=> [{:name=>"Guy1", :age=>46}, {:name=>"Guy3", :age=>45}] 

array1 | array2 
=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy1", :age=>46}, {:name=>"Guy3", :age=>45}] 

Sendika/kesişim/fark almanın ve yaş anahtarını yok saymanın bir yolu var mı?

düzenleme: Yardımlarınız için şimdiden

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}] 
array2 = [{:name =>'Guy1'},{:name =>'Guy3'}] 

p array1 - array2 
p array2 - array1 
p array1 | array2 
p array1 & array2 

Teşekkür: Daha iyi bir örnek!

+0

Beklenen sonuç, özellikle de:: yaşın değeri nedir? – sawa

+0

Beklenen sonuç, "yaş" mevcut değildi. –

+0

beklenen sonuç, ilk örnekte olduğu gibi olacaktır. –

cevap

5

İşte birliği almanın hızlı ve kirli yolu: Cary Swoveland işaret şekilde güvenle eql? geçersiz kılabilir Hash kendi alt sınıfını yaratıyor öneriyoruz, ancak

(array1 + array2).uniq{|a| a[:name]} 

neyi seti benzeri operatörler güveniyor. Ayrıca, ad alanı üzerinde karma işlevini sağlamak için hash yöntemini de sınırlamanız gerektiğini unutmayın.

class Guy < Hash 

    def eql?(other_hash) 
    self[:name] == other_hash[:name] 
    end 

    def hash 
    self[:name].hash 
    end 

end 

Sonra bu Guy nesneler kümesi operasyonlarının tümünde çalışır:

array1 = [ Guy[name:'Guy1', age: 45], Guy[name:'Guy2', age: 45] ] 
array2 = [ Guy[name:'Guy1', age: 46], Guy[name:'Guy3', age: 45] ] 

array1 - array2 
#=> [{:name=>"Guy2", :age=>45}] 

array2 - array1 
#=> [{:name=>"Guy3", :age=>45}] 

array1 | array2 
#=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy3", :age=> 
45}] 

array1 & array2 
#=> [{:name=>"Guy1", :age=>45}] 
+0

bile tehlikeli olabilir sınıflara, fakat evet, 'Hash' sınıfından ile işe yaramaz daha iyi. 'Guy' nesneleri g' 'f' ve' bir yanlışlıkla 'f.eql? (G) de kullanabilir ise' f == g' amaçlanan zaman' ('EQL değişen? '' '= Etkilemez), Bu oldukça kötü bir hataya neden olabilir. –

0

fark için:

diff_arr = array1.map{|a| a[:name]} - array2.map{|a| a[:name]} 

diff_arr.map{|a| array1.map{|s| s if s[:name] == a }}.flatten.compact 

Kavşak

intersec_arr = array1.map{|a| a[:name]} & array2.map{|a| a[:name]} 

intersec_ar.map{|a| array1.map{|s| s if s[:name] == a }}.flatten.compact 
0

Her üç sınıf Array yöntemleri, her ikisi de karma olan iki öğeyi karşılaştırmak için Hash#eql? numaralı kullanımla ilgilidir. (Hash#eql?, iki karma için karma kodların eşit olup olmadığını denetler.) Bu nedenle, yalnızca (geçici olarak) Hash#eql? yeniden tanımlamamız gerekiyor. Bu self açık olmalıdır o birkaç durumlardan biri olduğunu

array1 = [{:name =>'Guy1', :age => 45}, {:name =>'Guy2', :age => 45}] 
array2 = [{:name =>'Guy1'},    {:name =>'Guy3'}] 

class Hash 
    alias old_eql? eql? 
    def eql?(h) self[:name] == h[:name] end 
end 

array1 - array2 
    #=> [{:name=>"Guy2", :age=>45}] 
array2 - array1 
    #=> [{:name=>"Guy3"}] 
array1 | array2 
    #=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy3"}] 
array1 & array2 
    #=> [{:name=>"Guy1", :age=>45}] 

class Hash 
    alias eql? old_eql? # Restore eql? 
    undef_method :old_eql? 
end 

Not. diye yazarsak:

[:name] == h[:name] 

yerine:

self[:name] == h[:name] 

Yakut biz h[:name] ile dizi [:name] karşılaştırdığınız olduğu varsayılabilir.

+2

nedeniyle bir çekirdek sınıfın 'Hash' maymun yama için bu yaklaşımı tavsiye etmem. Ancak, OP yeni bir sınıf oluşturuyorsa, ör. Sınıf Guys

+0

Ayrıca, bu işe yaramıyor. Sanırım bir şeyi unutuyorsunuz (ipucu için cevabımı görün). –

+0

İyi puanlar, @Mark. Esas olarak bu çözümü öne sürdüm çünkü eğitim değeri olduğunu düşündüm. Yazarken ince buzda kayma olduğunu biliyordum; En azından bazı uyarıcı kelimeler eklemeliydim. Ben Sorununuza bir yorumda değineceğim gibi - - ama az çok Hash' 'müdahele bile daha Hash' tehlikeli olabilir' sınıflara. İkinci noktanızı ayrı bir yorumda ele alacağım. –