Создание хэша условным образом
Я использую Ruby on Rails 3.0.10, и я хотел бы построить хэш-ключ\значение пары условным образом. То есть, я хотел бы добавить ключ и его связанное значение, если условие согласовано:
hash = {
:key1 => value1,
:key2 => value2, # This key2\value2 pair should be added only 'if condition' is 'true'
:key3 => value3,
...
}
Как я могу это сделать и сохранить "хорошую" читаемость кода? Я "принудительно" использовал метод merge
?
Ответы
Ответ 1
Я предпочитаю tap
, так как я думаю, что он обеспечивает более чистое решение, чем описанное здесь, не требуя какого-либо взломанного удаления элементов и четко определяя область, в которой строится хэш.
Это также означает, что вам не нужно объявлять ненужную локальную переменную, которую я всегда ненавижу.
Если вы еще не встретили его, tap
очень прост - это метод на Object
, который принимает блок и всегда возвращает объект, на который он был вызван. Таким образом, чтобы создать хэш условно, вы можете сделать это:
Hash.new.tap do |my_hash|
my_hash[:x] = 1 if condition_1
my_hash[:y] = 2 if condition_2
...
end
Существует много интересных применений для tap
, это всего лишь один.
Ответ 2
Функциональный подход:
hash = {
:key1 => 1,
:key2 => (2 if condition),
:key3 => 3,
}.compact
Примечание. Для Ruby <2.4.0 или без активной поддержки замените .compact
на .reject { |k, v| v.nil? }
.reject { |k, v| v.nil? }
.reject { |k, v| v.nil? }
Ответ 3
Вероятно, лучше сохранить простоту, если вы беспокоитесь о читабельности:
hash = {}
hash[:key1] = value1
hash[:key2] = value2 if condition?
hash[:key3] = value3
...
Ответ 4
Будь проще:
hash = {
key1: value1,
key3: value3,
}
hash[:key2] = value2 if condition
Таким образом, вы также визуально отделяете свой особый случай, который может остаться незамеченным, если он похоронен в хеш-буквальном присваивании.
Ответ 5
Я использую merge
и тернарный оператор для этой ситуации,
hash = {
:key1 => value1,
:key3 => value3,
...
}.merge(condition ? {:key2 => value2} : {})
Ответ 6
Сначала создайте свой хэш:
hash = {
:key1 => value1,
:key2 => condition ? value2 : :delete_me,
:key3 => value3
}
Затем сделайте это после создания хеша:
hash.delete_if {|_, v| v == :delete_me}
Если ваш хеш не заморожен или не может быть неизменным, это фактически приведет только к сохранению значений.
Ответ 7
Если вы создадите хеш из каких-то переменных Enumerable, вы можете использовать впрыск, например:
raw_data.inject({}){ |a,e| a[e.name] = e.value if expr; a }
Ответ 8
Просто, как это:
hash = {
:key1 => value1,
**(condition ? {key2: value2} : {})
}
Надеюсь, что это поможет!
Ответ 9
Использование fetch может быть полезно, если вы заполняете хэш из дополнительных атрибутов где-то еще. Посмотрите на этот пример:
def create_watchable_data(attrs = {})
return WatchableData.new({
id: attrs.fetch(:id, '/catalog/titles/breaking_bad_2_737'),
titles: attrs.fetch(:titles, ['737']),
url: attrs.fetch(:url, 'http://www.netflix.com/shows/breaking_bad/3423432'),
year: attrs.fetch(:year, '1993'),
watchable_type: attrs.fetch(:watchable_type, 'Show'),
season_title: attrs.fetch(:season_title, 'Season 2'),
show_title: attrs.fetch(:id, 'Breaking Bad')
})
end
Ответ 10
Та же идея, что и Крис Джет-Янг, с легкой удобочитаемостью
def cond(x)
condition ? x : :delete_me
end
hash = {
:key1 => value1,
:key2 => cond(value2),
:key3 => value3
}
а затем postprocess для удаления записей :delete_me