Băm loại bỏ tất cả ngoại trừ các khóa cụ thể


83

Tôi muốn xóa mọi khóa khỏi hàm băm ngoại trừ một khóa nhất định.

Ví dụ:

{
 "firstName": "John",
 "lastName": "Smith",
 "age": 25,
 "address":
 {
     "streetAddress": "21 2nd Street",
     "city": "New York",
     "state": "NY",
     "postalCode": "10021"
 },
 "phoneNumber":
 [
     {
       "type": "home",
       "number": "212 555-1234"
     },
     {
       "type": "fax",
       "number": "646 555-4567"
     }
 ]
}

Tôi muốn xóa mọi thứ ngoại trừ "firstName" và / hoặc "address"

Cảm ơn

Câu trả lời:


50

Một số tùy chọn khác:

h.select {|k,v| ["age", "address"].include?(k) }

Hoặc bạn có thể làm điều này:

class Hash
  def select_keys(*args)
    select {|k,v| args.include?(k) }
  end
end

Vì vậy, bây giờ bạn có thể chỉ cần nói:

h.select_keys("age", "address")

1
Tôi thích sử dụng mảng để nó rất nhanh chóng, dễ dàng thêm các khóa mới thay vì nhiều câu lệnh OR. Việc gia hạn Hash cũng là kinda mát :)
Jake Dempsey

1
Cảm ơn. Câu trả lời toàn diện hơn nhiều!
glarkou

Điều này chỉ dành cho đường ray? hay ruby ​​nói chung?
Fadi

276

Về slicethì sao?

hash.slice('firstName', 'lastName')
 # => { 'firstName' => 'John', 'lastName' => 'Smith' }

9
Câu hỏi không đề cập cụ thể đến Rails, nhưng nó được gắn thẻ như vậy. Đây là tùy chọn tốt nhất khi sử dụng Rails hoặc core_ext.
Caleb Hearth

3
Vâng, đây là lý do tôi đề nghị slice.
Mario Uher

câu trả lời này phải là câu trả lời đầu tiên!
mmike

@DimaMelnik Hashes vốn dĩ không có đơn đặt hàng.
Joshua Pinter

2
Hash # slice bây giờ là Ruby thuần túy, không cần Rails.
akim

6

Hash # select thực hiện những gì bạn muốn:

   h = { "a" => 100, "b" => 200, "c" => 300 }
   h.select {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}
   h.select {|k,v| v < 200}  #=> {"a" => 100}

Chỉnh sửa (cho nhận xét):

giả sử h là hàm băm của bạn ở trên:

h.select {|k,v| k == "age" || k == "address" }

Điều gì sẽ xảy ra nếu tôi muốn chọn "tuổi" và "địa chỉ" từ ví dụ của mình?
glarkou

2

Nếu bạn sử dụng Rails, vui lòng xem xét except()phương pháp ActiveSupport : http://apidock.com/rails/Hash/except

hash = { a: true, b: false, c: nil}
hash.except!(:c) # => { a: true, b: false}
hash # => { a: true, b: false }

20
Ngoại trừ giữ mọi thứ ngoại trừ những gì đã cho. Mặt trái của câu hỏi là về cái gì.
Christopher Oezbek

1

Lấy cảm hứng từ câu trả lời của Jake Dempsey, câu trả lời này sẽ nhanh hơn đối với các hàm băm lớn, vì nó chỉ tạo đỉnh các khóa rõ ràng thay vì lặp lại toàn bộ hàm băm:

class Hash
  def select_keys(*args)
    filtered_hash = {}
    args.each do |arg|
      filtered_hash[arg] = self[arg] if self.has_key?(arg)
    end
    return filtered_hash
  end
end

0

Không cần Rails để có được một mã rất ngắn gọn:

keys = [ "firstName" , "address" ]
# keys = hash.keys - (hash.keys - keys) # uncomment if needed to preserve hash order
keys.zip(hash.values_at *keys).to_h

0
hash = { a: true, b: false, c: nil }
hash.extract!(:c) # => { c: nil }
hash # => { a: true, b: false }

Điều này loại trừ các khóa được chỉ định, thay vì bao gồm các khóa được chỉ định. sự khác biệt là nhỏ nhưng quan trọng
BKSpurgeon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.