我有一个查看5个变量的if,其中一些可能是nil。我有以下代码工作,但它感觉非常混乱。它使用的假设是被测试的字符串不是100 *,但它不能,但不管这是否有更好的方法。
m['search2'] = '*' * 100 if m['search2'].nil?
m['search3'] = '*' * 100 if m['search3'].nil?
m['exclude1'] = '*' * 100 if m['exclude1'].nil?
m['exclude2'] = '*' * 100 if m['exclude2'].nil?
if ( @title.upcase.index( m['search1'] ) || @title.upcase.index( m['search2']) || @title.upcase.index( m['search3']) ) &&
!(@title.upcase.index( m['exclude1']) || @title.upcase.index( m['exclude1']) ) then
exclude = true
end
只是为了澄清,鉴于答案涉及设置默认值的更好方法,虽然这很好,但我希望我能在if中做一些聪明的事情,因为它实际上必须设置默认值,感觉很乱。 / p>
答案 0 :(得分:1)
除非您处理的情况是,无论出于何种原因,其中一个值可能是文字false
,那么您的生活将非常方便。只需定义一些默认值:
DEFAULT_TERM = '*' * 100
DEFAULTS = {
'search2' => DEFAULT_TERM,
'search3' => DEFAULT_TERM,
'exclude1' => DEFAULT_TERM,
'exclude2' => DEFAULT_TERM
}
然后您可以将其合并到:
m = DEFAULTS.merge(m)
m
中未定义的任何内容将自动保留为默认值。您可能需要先清理m
:
m = DEFAULTS.merge(m.compact)
删除任何nil
值。
需要注意的另一件事是省略像then
这样的虚假语法。这没有必要,而且基本上没用。
如果您将结构重新组织成这样的结构,那么您可以更轻松地实施更灵活的搜索:
{
'search' => [ 'term1', 'term2', 'term3' ],
'exclude' => [ 'exclude1', 'exclude2', 'exclude3' ]
}
从那时起,您可以使用简单的迭代。
答案 1 :(得分:1)
从简化开始:
m['search2'] = '*' * 100 if m['search2'].nil?
更好地表达为:
m['search2'] ||= '*' * 100
然后使整个事物成为一个循环(为了清晰起见,也使字符串变为常量):
STARS = '*' * 100
%w(search2 search3 exclude3 exclude2).each { |key|
m[key] ||= STARS
}
虽然如果你只是默认这样做,那么有一个更好的方式,如tadman所说。
答案 2 :(得分:1)
无论何时重复代码,都应该考虑使用循环或方法。这是一个使用循环的示例,以便您可以避免重写
search_keys = ['search2', 'search3']
exclude_keys = ['exclude1', 'exclude2']
search_keys.each do |key|
m[key] = '*' * 100 if m[key].nil?
end
exclude_keys.each do |key|
m[key] = '*' * 100 if m[key].nil?
end
答案 3 :(得分:1)
似乎你正在尝试解决你在String#index
上传递的错误,当它作为参数传递时,而不是它预期的字符串。
在这种情况下,如果你考虑一下你真正想要达到的目标,那就有一个更简单(更惯用的解决方案)。在您的情况下,如果exclude
包含任意可选的搜索字词,则您希望将true
设置为@title
,并排除任何可选的排除字词。
这可以通过以下方法实现。请注意,如果不是带有“魔术”键名称的Hash
,您可以将术语设为两个数组,一个用于搜索术语,一个用于排除术语。然后,您的方法也可以扩展为更多术语,而无需进行调整。
def exclude?(m)
# upcase the @title only once for performance
upcased_title = @title.upcase
# Depending on the m argument, you might be able to further
# improve this to get rid of the repetition
exclude_terms = [
m['exclude1'],
m['exclude2']
].compact
# ^^^^^^^ Compacting on an array gets rid on any nil values
# Same here.
search_terms = [
m['search1'],
m['search2'],
m['search3']
].compact
# ^^^^^^^ Same for the search terms
# We use include? instead of index to better convey our meaning
return false if exclude_terms.any? { |term| upcased_title.include?(term) }
return true if search_terms.any? { |term| upcased_title.include?(term) }
# TODO: what should happen in neither an exclude term nor
# a search term was found?
end
请注意,您的问题中的条件似乎是倒退的。如果搜索字词匹配但没有排除字词,则将exclude
设置为false。你可能的意思恰恰相反。