以条件方式构建哈希

时间:2011-09-07 03:43:52

标签: ruby hash conditional

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

11 个答案:

答案 0 :(得分:54)

我更喜欢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 :(得分:25)

功能性方法:

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

注意:对于Ruby< 2.4.0或不使用主动支持,将.compact替换为.reject { |k, v| v.nil? }

答案 2 :(得分:9)

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

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

答案 3 :(得分:4)

保持简单:

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

hash[:key2] = value2 if condition

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

答案 4 :(得分:3)

我使用library(ggplot2) library(gridExtra) p <- ggplot(data = df, aes(x = Species, y = Sepal.Length)) + geom_point() + stat_summary(aes(shape="mean"), fun.y=mean, size = 6, shape=95, colour="black", geom="point") + theme_bw() + theme(axis.text.x = element_text(angle=45, hjust=1, vjust=1)) annot <- ggplot(data=df_stats, aes(x=Species, y = 0)) + geom_text(aes(label=stat_txt), hjust=0) + theme_minimal() + scale_x_discrete(breaks=NULL) + scale_y_continuous(breaks=NULL) + xlab(NULL) + ylab('') grid.arrange(annot, p, heights=c(1,8)) 和三元运算符来处理这种情况,

merge

答案 5 :(得分:2)

首先构建你的哈希:

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

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

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

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

答案 6 :(得分:1)

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

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

答案 7 :(得分:1)

这很简单:

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

希望它有所帮助!

答案 8 :(得分: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

答案 9 :(得分:0)

如果要在单个条件下添加几个键,可以使用merge

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

if condition
  hash.merge!(
    :key5 => value4,
    :key5 => value5,
    :key6 => value6
  )
end

hash

答案 10 :(得分:-1)

与Chris Jester-Young相同的想法,带有轻微的可读性技巧

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

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

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