以条件方式构建哈希

问题描述 投票:36回答:10

我正在使用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方法?

ruby hash conditional
10个回答
55
投票

我更喜欢tap,因为我认为它提供了比这里描述的更清晰的解决方案,不需要任何hacky删除元素,并清楚地定义哈希的构建范围。

这也意味着你不需要声明一个我总是讨厌的不必要的局部变量。

如果您之前没有碰到它,tap非常简单 - 它是Object上的一个方法,它接受一个块并始终返回它被调用的对象。因此,要有条件地构建哈希,您可以这样做:

Hash.new.tap do |my_hash|
  my_hash[:x] = 1 if condition_1
  my_hash[:y] = 2 if condition_2
  ...
end

tap有许多有趣的用途,这只是一个。


-1
投票

和Chris Jester-Young一样,带有轻微的可读性技巧

def cond(x)
  condition ? x : :delete_me
end

hash = {
  :key1 => value1,
  :key2 => cond(value2),
  :key3 => value3
}

然后进行后处理以删除:delete_me条目


25
投票

功能方法:

hash = {
  :key1 => 1,
  :key2 => (2 if condition),
  :key3 => 3,
}.compact 

注意:对于Ruby <2.4.0或不使用active-support,请用.compact替换.reject { |k, v| v.nil? }


9
投票

如果您担心可读性,可能最好保持简单:

hash = {}
hash[:key1] = value1
hash[:key2] = value2 if condition?
hash[:key3] = value3
...

4
投票

把事情简单化:

hash = {
  key1: value1,
  key3: value3,
}

hash[:key2] = value2 if condition

通过这种方式,您还可以直观地分离您的特殊情况,如果它隐藏在散列字面值分配中,则可能会被忽略。


3
投票

我使用merge和三元运算符来处理这种情况,

hash = {
  :key1 => value1,
  :key3 => value3,
  ...
}.merge(condition ? {:key2 => value2} : {})

2
投票

首先构建你的哈希:

hash = {
  :key1 => value1,
  :key2 => condition ? value2 : :delete_me,
  :key3 => value3
}

然后在构建哈希之后执行此操作:

hash.delete_if {|_, v| v == :delete_me}

除非您的哈希被冻结或以其他方式不可变,否则这实际上只会保留存在的值。


1
投票

如果您从某种Enumerable数据构建哈希,则可以使用inject,例如:

raw_data.inject({}){ |a,e| a[e.name] = e.value if expr; a }

1
投票

很简单:

hash = {
  :key1 => value1,
  **(condition ? {key2: value2} : {})
}

希望能帮助到你!


0
投票

如果您从其他位置的可选属性填充哈希值,则使用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
© www.soinside.com 2019 - 2024. All rights reserved.