Хеш видаляє всі, крім конкретних клавіш


83

Я хотів би видалити кожен ключ з хешу, крім даного ключа.

Наприклад:

{
 "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"
     }
 ]
}

Я хочу видалити все, крім "Ім'я" та / або "адреса"

Дякую

Відповіді:


50

Деякі інші варіанти:

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

Або ви можете зробити це:

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

Тож тепер ви можете просто сказати:

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

1
Мені подобається використовувати масив, так що його дуже швидко можна легко додати нові ключі замість більше операторів АБО. Розширення Hash також є якось крутим :)
Джейк Демпсі,

1
Дякую. Набагато вичерпніша відповідь!
glarkou

Це лише для рейок? чи взагалі рубін?
Фаді

276

Що про slice?

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

9
У запитанні не згадувалось спеціально Rails, але воно позначене як таке. Це найкращий варіант при використанні Rails або core_ext.
Калеб Харт

3
Так, це причина, яку я запропонував slice.
Mario Uher

ця відповідь повинна бути першою!
mmike

Хеш @DimaMelnik за своєю суттю не має порядку.
Джошуа Пінтер,

2
Хеш # фрагмент - це чистий Ruby, Rails не потрібні.
акім

6

Хеш # select робить те, що ви хочете:

   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}

Редагувати (для коментарів):

припустивши, що h є вашим хешем вище:

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

Що робити, якщо я хочу вибрати "вік" та "адресу" зі свого прикладу?
glarkou


1

Натхненний відповіддю Джейка Демпсі, він повинен бути швидшим для великих хешів, оскільки він піднімає лише явні ключі, а не перебирає весь хеш:

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

Для отримання дуже стислого коду не потрібні Rails:

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 }

Це виключає вказані ключі, а не включає вказані ключі. різниця
незначна,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.