如何只选择一次运算符,而不是在循环中重复测试?
How to choose an operator just one time, instead of repeating the test inside a loop?
这是我要重构的内容:
items.each_with_index do |item, ndx|
if side == :left
condition = ndx < max
else
condition = ndx >= max
end
result_items << item if condition
end
我希望能够将 if/else/end 移到块外,因为 side
的值在块内永远不会改变。由于根据 side
的值唯一改变的是运算符,我希望能够做类似的事情:
if side == :left
oper = <
else
oper = >=
end
items.each_with_index do |item, ndx|
result_items << item if ndx oper max
end
但是,当然,由于语法原因,这行不通。
有没有存储运算符的方法,或者有更好的方法来完成我在这里的任务?
查看 "proc" 和 "lambda"。它们使您能够持有对匿名函数的引用:
[4] pry(main)> func = proc {|left, right| left < right}
=> #<Proc:0x34c83c0@(pry):4>
[5] pry(main)> func.call(4,5)
=> true
[6] pry(main)> func.call(5,2)
=> false
请注意,'proc' 需要传递 "block",并且稍后将使用给定的参数 "call" 编辑该块。这与您使用 map
或 each
的语法相同 - 这就是所有块。 proc
只需 returns 阻止而不是调用它。
因此,您的代码类似于:
if side == :left
oper = proc{|a,b| a<b}
else
oper = proc{|a,b| a>=b}
end
items.each_with_index do |item, ndx|
result_items << item if oper.call(ndx, max)
end
我没有检查过那个代码,可能有一些错别字。
运算符只是方法:
ndx.public_send(:<=, max)
与
相同
ndx <= max
因此在循环外将 oper
设置为所需运算符的符号,并在循环内设置
result_items << item if ndx.public_send(oper, max)
(如果您仍然停留在 1.8,则必须使用 send
而不是 public_send
)
如果我理解你的意图,另一种方法是使用 take
和 drop
:
result_items = if side == :left
items.take max
else
items.drop max
end
如果你可以稍微调整一下这个逻辑,你也可以达到同样的效果:
items.each_with_index do |item, ndx|
# assuming it to be Fixnum since you are using index value
result_items << item if (max - ndx).abs >= 0
end
这是我要重构的内容:
items.each_with_index do |item, ndx|
if side == :left
condition = ndx < max
else
condition = ndx >= max
end
result_items << item if condition
end
我希望能够将 if/else/end 移到块外,因为 side
的值在块内永远不会改变。由于根据 side
的值唯一改变的是运算符,我希望能够做类似的事情:
if side == :left
oper = <
else
oper = >=
end
items.each_with_index do |item, ndx|
result_items << item if ndx oper max
end
但是,当然,由于语法原因,这行不通。
有没有存储运算符的方法,或者有更好的方法来完成我在这里的任务?
查看 "proc" 和 "lambda"。它们使您能够持有对匿名函数的引用:
[4] pry(main)> func = proc {|left, right| left < right}
=> #<Proc:0x34c83c0@(pry):4>
[5] pry(main)> func.call(4,5)
=> true
[6] pry(main)> func.call(5,2)
=> false
请注意,'proc' 需要传递 "block",并且稍后将使用给定的参数 "call" 编辑该块。这与您使用 map
或 each
的语法相同 - 这就是所有块。 proc
只需 returns 阻止而不是调用它。
因此,您的代码类似于:
if side == :left
oper = proc{|a,b| a<b}
else
oper = proc{|a,b| a>=b}
end
items.each_with_index do |item, ndx|
result_items << item if oper.call(ndx, max)
end
我没有检查过那个代码,可能有一些错别字。
运算符只是方法:
ndx.public_send(:<=, max)
与
相同ndx <= max
因此在循环外将 oper
设置为所需运算符的符号,并在循环内设置
result_items << item if ndx.public_send(oper, max)
(如果您仍然停留在 1.8,则必须使用 send
而不是 public_send
)
如果我理解你的意图,另一种方法是使用 take
和 drop
:
result_items = if side == :left
items.take max
else
items.drop max
end
如果你可以稍微调整一下这个逻辑,你也可以达到同样的效果:
items.each_with_index do |item, ndx|
# assuming it to be Fixnum since you are using index value
result_items << item if (max - ndx).abs >= 0
end