@JanDvorak Этот вопрос касается не только возврата субхэша, но и изменения существующего. Очень похожие вещи, но ActiveSupport предлагает разные способы их решения.
skalee 05
Ответы:
59
Если вы специально хотите, чтобы метод возвращал извлеченные элементы, но h1 оставался прежним:
Это O (n2) - у вас будет один цикл для выбора, другой цикл для включения, который будет называться h1.size times.
metakungfu
1
Хотя этот ответ подходит для чистого рубина, если вы используете рельсы, приведенный ниже ответ (с использованием встроенного sliceили except, в зависимости от ваших потребностей) намного чище
Krease
138
ActiveSupport, По крайней мере , так как 2.3.8, обеспечивает четыре удобные методы: #slice, #exceptи их разрушительные аналоги: #slice!и#except! . Они упоминались в других ответах, но суммировать их в одном месте:
Обратите внимание на возвращаемые значения методов взрыва. Они не только адаптируют существующий хэш, но и возвращают удаленные (не сохраненные) записи. ВHash#except! костюмах лучший примера , приведенный в этом вопросе:
x ={a:1, b:2, c:3, d:4}# => {:a=>1, :b=>2, :c=>3, :d=>4}
x.except!(:c,:d)# => {:a=>1, :b=>2}
x
# => {:a=>1, :b=>2}
ActiveSupportне требует целых Rails, довольно легкий. Фактически, от него зависит множество не-рельсовых гемов, поэтому, скорее всего, он у вас уже есть в Gemfile.lock. Нет необходимости расширять класс Hash самостоятельно.
ИМО, исправление Mokey - это, безусловно, путь. Намного чище и проясняет намерения.
Romário
1
Добавить, чтобы изменить код для адресации corectly core module, определить модуль и импортировать расширение Hash core ... модуль CoreExtensions модуль Hash def slice (* keys) :: Hash [[keys, self.values_at (* keys)]. Transpose] end end end Hash.include CoreExtensions :: Hash
Думаю, вы описываете экстракт !. извлечь! удаляет ключи из начального хеша, возвращая новый хеш, содержащий удаленные ключи. ломтик! делает обратное: удаляет все ключи, кроме указанных, из начального хеша (опять же, возвращает новый хеш, содержащий удаленные ключи). Так что кусочек! это немного больше похоже на операцию «сохранить».
Хорошая работа. Не совсем то, о чем он просит. Ваш метод возвращает: {: d =>: D,: b =>: B,: e => nil,: f => nil} {: c =>: C,: a =>: A,: d => : D,: b =>: B}
Энди,
Эквивалентное однострочное (и, возможно, более быстрое) решение: <pre> def subhash(*keys) select {|k,v| keys.include?(k)} end
Ответы:
Если вы специально хотите, чтобы метод возвращал извлеченные элементы, но h1 оставался прежним:
И если вы хотите исправить это в классе Hash:
Если вы просто хотите удалить указанные элементы из хеша, это намного проще с помощью delete_if .
источник
slice
илиexcept
, в зависимости от ваших потребностей) намного чищеActiveSupport
, По крайней мере , так как 2.3.8, обеспечивает четыре удобные методы:#slice
,#except
и их разрушительные аналоги:#slice!
и#except!
. Они упоминались в других ответах, но суммировать их в одном месте:Обратите внимание на возвращаемые значения методов взрыва. Они не только адаптируют существующий хэш, но и возвращают удаленные (не сохраненные) записи. В
Hash#except!
костюмах лучший примера , приведенный в этом вопросе:ActiveSupport
не требует целых Rails, довольно легкий. Фактически, от него зависит множество не-рельсовых гемов, поэтому, скорее всего, он у вас уже есть в Gemfile.lock. Нет необходимости расширять класс Hash самостоятельно.источник
x.except!(:c, :d)
(на ура) должен быть# => {:a=>1, :b=>2}
. Хорошо, если ты сможешь отредактировать свой ответ.Если вы используете рельсы , вам подойдет Hash # slice .
Если вы не используете рельсы , Hash # values_at вернет значения в том же порядке, в каком вы их просили, поэтому вы можете сделать это:
пример:
Пояснение:
Из
{:a => 1, :b => 2, :c => 3}
мы хотим{:a => 1, :b => 2}
Если вам кажется, что исправление обезьян - это лучший способ, вам нужно следующее:
источник
Ruby 2.5 добавил Hash # slice :
источник
Вы можете использовать slice! (* Ключи), который доступен в основных расширениях ActiveSupport.
initial_hash теперь будет
extract_slide теперь будет
Вы можете посмотреть на
slice.rb in ActiveSupport 3.1.3
источник
источник
def subhash(*keys) select {|k,v| keys.include?(k)} end
источник
если вы используете рельсы, может быть удобно использовать Hash.except
источник
источник
Вот быстрое сравнение производительности предложенных методов,
#select
кажется, самый быстрыйДоработка будет выглядеть так:
И использовать это:
источник
Оба
delete_if
иkeep_if
являются частью ядра Ruby. Здесь вы можете добиться желаемого, не исправляяHash
тип.Для получения дополнительной информации ознакомьтесь с приведенными ниже ссылками в документации:
источник
Как уже упоминалось, Ruby 2.5 добавил метод Hash # slice.
Rails 5.2.0beta1 также добавил свою собственную версию Hash # slice, чтобы облегчить функциональность для пользователей фреймворка, использующих более раннюю версию Ruby. https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8
Если вы хотите реализовать свой собственный по какой-либо причине, это тоже хороший лайнер:
источник
Этот код внедряет функции, которые вы запрашиваете, в класс Hash:
и дает результаты, которые вы предоставили:
Примечание: этот метод фактически возвращает извлеченные ключи / значения.
источник
Вот функциональное решение, которое может быть полезно, если вы не используете Ruby 2.5 и не хотите загрязнять свой класс Hash, добавляя новый метод:
Затем вы можете применить его даже к вложенным хешам:
источник
Просто дополнение к методу среза, если ключи субхэша, которые вы хотите отделить от исходного хеша, будут динамическими, вы можете сделать это так:
источник
Мы можем сделать это, перебирая только те ключи, которые мы хотим извлечь, и просто проверяя, существует ли ключ, а затем извлекаем его.
источник