如果是expression.nil?然后表达别的其他表达

时间:2013-12-24 17:35:04

标签: ruby

当我想要评估某个表达式时,我发现自己经常会看到一个模式,如果为true,则给出表达式的结果,或者如果为false则执行其他类似的表达式。例如

if hours.detect { |h| h.position > i && h.open == true }.nil?
  hours.detect { |h| h.position >= 0 && h.open == true }
else
  hours.detect { |h| h.position > i && h.open == true }
end

这段代码似乎很冗余。有人可以建议一种更优雅的方式吗?

谢谢!

6 个答案:

答案 0 :(得分:2)

尝试代码:

hh = hours.select {|h| h.open == true }
hh.detect { |h| h.position > i } || hh.detect { |h| h.position >= 0 }

在大多数情况下(当h.open返回一个布尔值时),它可以转换为以下一个:

hh = hours.select {|h| h.open }
hh.detect { |h| h.position > i } || hh.detect { |h| h.position >= 0 }

答案 1 :(得分:0)

我会这样做:

hh_true = hours.select {|h| h.open == true }
prc = prc hh_true.detect { |h| h.position >= 0 }
hh_true.detect(prc) { |h| h.position > i }

举例说明:

ary = ['fooo','fooo','foo']
prc = proc {ary.find{|e| e.size == 3}}
ary.detect(prc){|e| e.size == 5}
# => "foo"
ary.detect(prc){|e| e.size == 4 }
# => "fooo"

答案 2 :(得分:0)

您可以先创建方法

def detect_hours(i)
  hours.detect { |h| h.position > i && h.open }
end

然后只使用下面的

detect_hours(i) || detect_hours(0)

答案 3 :(得分:0)

最直接的解决方案是:

hours.detect { |h| h.position >  i && h.open == true } || \
hours.detect { |h| h.position >= 0 && h.open == true }

但它效率最高吗?乍一看,人们不会想到,最好先select hours h.open == true detect。但回想一下hours一旦找到真实条件就退出,这可能是第一个块中hours的第一个元素或第二个块中h.position > i的最后一个元素。相对效率取决于数据。如果select通常为真,则可能比首先执行hours要快,这需要完全遍历&&。如果效率很重要,可以对此进行测试,以及在每个块中反转两个{{1}} ed条件的效果。

答案 4 :(得分:0)

hours.sort! { |h1,h2|
  ((-1 if h1.open == false) || (1 if h1.position > i) || (0 if h1.position >= 0)) <=>
  ((-1 if h2.open == false) || (1 if h2.position > i) || (0 if h2.position >= 0))
}
hours[0] if hours[0].open

我认为这有效,但我不是百分百肯定。基本上,将hours映射到一个数字,对这些数字进行排序,它将是第一个元素。

如果您不希望有任何h.position > i个案例,这样会更好,因为您无论如何都必须检查整个阵列。

或者,虽然我不确定语法,但请使用ifnone中的detect功能:

hours.find(lambda{hours.find{|h| h.open && h.position > 0}}){|h| h.open && h.position > i}

答案 5 :(得分:0)

hours.detect { |h| h.position > i && h.open == true }重复完全两次。在许多语言中,您可以将其存储到某个变量中:

var1 = hours.detect { |h| h.position > i && h.open == true }

然后在你的if中,你可以替换它:

if var1.nil?
  hours.detect { |h| h.position >= 0 && h.open == true }
else
  var1
end

您可以使用nil?

来摆脱unless
var1 = hours.detect { |h| h.position > i && h.open == true }
unless var1
  hours.detect { |h| h.position >= 0 && h.open == true }
else
  var1
end

在此if中,hours.detect完全相同。您可以将其提取到方法/ lambda / proc中。这是方法版本:

def hourse_detect hours, &lam # `&` change block of code into variable(`proc` / `lambda`) OR variable(`proc` / `lambda`) into block of code
  hours.detect &lam #detect need block of code not `proc` / `lambda`
end

您可以存储{}之间存在的代码块(或do / end):

block1 =  proc { |h| h.position > i && h.open == true }
block2 =  proc { |h| h.position >= 0 && h.open == true }

以下是使用以上功能的完整代码:

def hourse_detect hours, &lam
  hours.detect &lam
end
block1 =  proc { |h| h.position > i && h.open == true }
block2 =  proc { |h| h.position >= 0 && h.open == true }
var1 = hourse_detect hours, &block1
unless var1
  hours_detect hours, &block2
else
  var1
end

h.open == true可以转换为:

def opened? hour
  hours.open == true
end