我有一个数组,我想根据一组规则删除某些元素。我已经编写了以下代码:
puts "before: #{people.inspect()}"
puts people.size
people.delete_if do |person|
rules.each do |rule|
if rule.check_source(self) && !rule.check_rule(person)
puts "deleted person #{person.id}"
true
puts "sanity check"
end
end
false
end
puts "after: #{people.inspect()}"
但该代码不起作用。之前打印的阵列与之后打印的阵列相同,并且"完整性检查"虽然我认为它不应该被打印出来。我怀疑问题可能是因为delete_if块中的循环,但我不知道如何解决这个问题。
这是在一个包含2个ID为2和3的人的数组之后的控制台输出,其中2应该被删除并保留3个:
before: [#<Person id: 2>, #<Person id: 3>]
2
deleted person 2
sanity check
after: [#<Person id: 2>, #<Person id: 3>]
答案 0 :(得分:2)
您的问题是,您传递给delete_if
的阻止总是评估为false
。你的代码结构是这样的:
people.delete_if do |person|
# Stuff that `delete_if` doesn't care about ...
false
end
each
块的值无关紧要,因为each
并不关心它返回的内容,delete_if
无论如何也永远不会看到它。 delete_if
和each
的阻止是独立的。
您可以使用更简单的any?
调用替换整个delete_if
块:
people.delete_if do |person|
rules.any? { |rule| rule.check_source(self) && !rule.check_rule(person) }
end
并获得您正在寻找的结果。
答案 1 :(得分:0)
它返回所有元素,因为你在块的末尾放置了false,delete_if函数删除了一个特定元素如果块评估条件为真,例如,考虑下面给出的代码
a=[1,2,4,5,6,7]
a.delete_if do |x|
x>5
end
puts a.inspect
输出
[1, 2, 4, 5]
块为6和7计算条件为真,因此从数组中删除这些元素。在您的情况下,因为您在块的末尾返回false,所有元素保持不变。例如,请考虑以下代码
a=[1,2,4,5,6,7]
a.delete_if do |x|
x>5
false
end
puts a.inspect
输出
[1, 2, 4, 5, 6, 7]
如果我在结尾处返回true,那么将删除所有元素,例如
a=[1,2,4,5,6,7]
a.delete_if do |x|
x>5
true
end
puts a.inspect
输出
[]
这就是你执行后所有元素保持不变的原因,请确保你在delete_if函数块中传递条件。
并且如果你在delete_if块中传递每个迭代器,它将返回相同的数组,但delete_if函数需要true来执行删除操作所以请确保你在块内给出条件。