基于具有循环

时间:2016-10-15 18:40:43

标签: ruby-on-rails arrays ruby

我有一个数组,我想根据一组规则删除某些元素。我已经编写了以下代码:

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>]

2 个答案:

答案 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_ifeach的阻止是独立的。

您可以使用更简单的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来执行删除操作所以请确保你在块内给出条件。