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