2013-05-28 34 views
5

Tôi hiện đang thử một số giờ để xóa khóa băm lồng nhau của danh sách băm. Tôi thấy nhiều giải pháp phi lồng nhau hashs Mà trông như thế này:Làm thế nào để loại bỏ các khóa lồng nhau khỏi danh sách băm trong Rails

sample_hash = {"key1" => "value1", "key2" => "value2"} 
    sample_hash.except("key1") 

Điều này dẫn đến:

{"key2"=>"value2"} 

Nhưng nếu tôi cố gắng sử dụng ngoại trừ phương pháp trên một băm với chìa khóa lồng nhau sau đó nó doesn 't làm việc. Ở đây mã của tôi:

nested_hash = {"key1"=>"value1", "key2"=>{ 
              "nested_key1"=>"nestedvalue1", 
              "nested_key2"=>"nestedvalue2" 
              } 
       } 

    nested_hash.except("nested_key2") 

except() phương thức trả về các nested_hash mà không cần bất kỳ thay đổi. Tôi đã tìm một giải pháp làm thế nào tôi có thể vượt qua lồng nhau băm phím để phương pháp ngoại trừ, nhưng không thể tìm thấy bất cứ điều gì. Thậm chí có thể truyền các khóa lồng vào phương thức này hay tôi nên sử dụng một số phương thức khác để xóa khóa băm lồng nhau khỏi danh sách băm của tôi?

+1

Có thể bạn muốn có cây thật chứ không phải là băm lồng nhau. Bạn có thể xem https://github.com/evolve75/RubyTree, https://github.com/stefankroes/ancestry hoặc https://github.com/mceachen/closure_tree để biết các đá quý có thể phù hợp với bạn. –

Trả lời

8

gì về

Hash[nested_hash.map {|k,v| [k,(v.respond_to?(:except)?v.except("nested_key2"):v)] }] 

=> {"key1"=>"value1", "key2"=>{"nested_key1"=>"nestedvalue1"}} 

ugh.

+0

Nó hoạt động! Rất cám ơn thats những gì tôi đã tìm kiếm. – user1367922

+0

Công trình này tuyệt vời, nhưng bạn có thể giải thích ký hiệu này không? Làm thế nào là từ khóa "Hash" tham gia vào một chỉ mục mảng, và tại sao chúng ta ánh xạ từng phần tử vào một mảng [k, v] hoặc [k, v.except ("nested_key2")]? –

+0

xem http://www.ruby-doc.org/core-2.0/Hash.html#method-c-5B-5D, phương pháp chuẩn để tạo băm. Nó chấp nhận danh sách khóa, giá trị, khóa, giá trị, ... hoặc các liên kết key => value, key => value, ... hoặc mảng lồng nhau, những gì chúng tôi sử dụng ở đây. –

0

thử

my_hash = Hash[nested_hash.map {|k,v| {k=>v.is_a? Array ? v.except("nested_key2") : v}}.map {|key, value| [key, value]}] 

Nhưng điều này dường như chậm phát triển, tôi ước gì mình chưa bao giờ bắt đầu xuống con đường này, tôi sẵn sàng đặt cược có một cách dễ dàng hơn!

+0

thx cho đề xuất của bạn. nhưng nó ném một NoMethodError: phương thức undefined 'except 'cho" value1 ": String – user1367922

+0

I; sẽ thêm một ngoại lệ – RadBrad

0

Giải pháp được chấp nhận là hợp lệ cho trường hợp được đưa ra nhưng nếu bạn đang tìm kiếm thứ gì đó sẽ làm điều này cho các bảng băm tùy ý lồng nhau thì bạn sẽ cần một giải pháp đệ quy. Tôi không thể tìm thấy một giải pháp phù hợp ở bất cứ đâu, vì vậy tôi đã viết một here.

sao chép ở đây với chú thích:

class Hash 
    def except_nested(key) 
    r = Marshal.load(Marshal.dump(self)) # deep copy the hashtable 
    r.except_nested!(key) 
    end 

    def except_nested!(key) 
    self.except!(key) 
    self.each do |_, v| # essentially dfs traversal calling except! 
     v.except_nested!(key) if v.is_a?(Hash) 
    end 
    end 
end 

thêm nó vào lớp Hash để bạn có thể gọi nó giống như cách bạn gọi trừ/trừ! bất cứ nơi nào khác.

t = { a: '1', b: { c: '3', d: '4' } } 

r = t.except_nested(:c) 
# r => {:a=>"1", :b=>{:d=>"4"}} 
# t => {:a=>"1", :b=>{:c=>"3", :d=>"4"}} 

t.except_nested!(:c) 
# t => {:a=>"1", :b=>{:d=>"4"}} 
Các vấn đề liên quan