我对Ruby的语法感到惊讶,我只能用一个词来描述:舒服。
编辑:我想我不清楚。我想要一种简单的方法来退出有条件的循环。
可悲的是,我找不到如何在Ruby中使用这个Java代码:
假设: 数组= [1,2,3,4] array2 = [1,2,3,4]
boolean condition = false;
for(int i = 0; i < array.length && !condition; i++)
{
for(int j = 0; j < array2.length && !condition; j++)
{
condition = (array[i] + array2[j] + 1 == 7);
}
}
if(condition)
{
System.out.println("Two elements of the arrays + 1 sum 7")
}
我喜欢Ruby的一个衬里......但是我甚至不能用完全开环来做这个......
我正在寻找类似这样的东西(each_while组成):
array.each_while(condition && condition2) { SomeAction }
在Ruby中执行此操作的最简单方法是什么?
我使用的大多数循环都有退出条件来优化它们。我在互联网上找到的所有东西都不能被Ruby的漂亮语法所接受,因为它比Java更糟糕,我们都知道Java并不漂亮。
我在网上找到了一些解决方案:
catch "BreakOuterLoop" do
for i in 1..10
print "out #{i}\n"
for j in 1..10
print "in #{j}\n"
throw "BreakOuterLoop" if i+j > 16
end
end
end
太糟糕了......
答案 0 :(得分:3)
您可以使用break
:
array1.each do |x|
break unless condition && condition2
array2.each do |y|
break unless condition3
# do_something
end
end
end
如果您需要条件中的指数:
array1.each_with_index do |x,i|
break unless condition && condition2
array2.each_with_index do |y,j|
break unless condition3
# do_something
end
end
end
对于您的更新问题,您可以使用any?
。这正是你想要做的。只要条件不是true
,它就会迭代,并返回一个值ASAP:
array = [1,2,3,4]
array2 = [1,2,3,4]
puts array.product(array2).any?{|a,b| a + b + 1 == 7 }
#=> true
或者:
puts array.any?{|a| array2.any?{ |b| a + b + 1 == 7 } }
#=> true
puts array.any?{|a| array2.any?{ |b| a + b + 1 == 12 } }
#=> false
第二个示例应该更快,因为并非每个对都被创建:只要找到一个,就会返回true
。
如果您想知道条件为true
的哪一对,您可以使用find
:
p array.product(array2).find { |a, b| a + b + 1 == 7 }
#=> [2,4]
p array.product(array2).find { |a, b| a + b + 1 == 12 }
#=> nil
对于大型数组,上述代码运行缓慢。
您可以将最大的数组转换为Set,并使用直接查找:
require 'set'
array = [1, 2, 3, 4]
array2 = [1, 2, 3, 4]
set2 = array2.to_set
sum = 7 - 1
x1 = array.find { |x| set2.include?(sum - x) }
if x1
puts "#{x1} + #{sum - x1} + 1 = #{sum + 1}"
end
#=> 2 + 4 + 1 = 7
答案 1 :(得分:3)
require 'matrix'
Matrix[0...rows, 0...cols].each_with_index do |e, row, col|
next unless [cond1, cond2, cond3].reduce :&
# code
end
array1.each.with_index.lazy.take_while { cond1 }.each do |e1, i1|
array2.each.with_index.lazy.take_while { cond2 }.each do |e2, i2|
# do some stuff
end
end
答案 2 :(得分:0)
array.length.times do |i|
break unless condition_1 && condition_2
# some action
end
只要条件不再符合, break
就会停止循环
关于循环矩阵
当然你可以在循环中的循环中嵌套循环,但这绝对不是 ruby方式。我确信对于可能出现的任何问题都有更好的解决方案。
答案 3 :(得分:0)
如前所述,对于您可以想到的任何特定用例,都有一个更漂亮的功能解决方案。我将尝试回答更一般的问题,即如何转换此java代码:
int somethingYouWillMutate = 0; // any types or values or number of things
for(int i = 0; i < array.length && condition && condition2; i++) {
for(int j = 0; j < array2.length && condition; j++) {
someAction(array[i], array2[j], somethingYouWillMutate);
}
}
红宝石:
something_you_will_mutate = 0
array.product(array2).each do |e1, e2|
break unless condition && condition2
some_action(e1, e2)
end
注意强>:
while c1 && c2 =:=
while true; break if !(c1 && c2) =:=
while true; break unless c1 && c2
如果你也想要指数:
array_indexed = array.each_with_index.to_a
array2_indexed = array2.each_with_index.to_a
array_indexed.product(array2_indexed).each do |(e1, i1), (e2, i2)|
break unless condition && condition2
some_action(e1, e2, i1, i2, something_you_will_mutate)
end
注意:如果您想要更通用的解决方案(例如,包含3个或更多数组):
[array, array2, array3...].
map(&:each_with_index).
map(&:to_a).
reduce(:product).
map(&:flatten).
each do |e1, i1, e2, i2, e3, i3...|
break unless condition && condition2 && condition3...
some_action(e1, e2, i1, i2, e3, i3..., something_you_will_mutate)
end