Подтвердить что ты не робот

Создание хэша условным образом

Я использую 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?

4b9b3361

Ответ 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