根据文档,#delete_at
返回该索引处的元素。
a = ["ant", "bat", "cat", "dog"]
a.delete_at(2) #=> "cat"
a #=> ["ant", "bat", "dog"]
a.delete_at(99) #=> nil
我加了一些调试语句向您展示在每一步发生的,假设极限是4:
@results = [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1], [1, 1]]
@results.each_with_index do |r, i|
puts "RESULT: #{r.to_s}"
puts "INDEX: #{i}"
@results.delete_at(i) if r.size < 4
puts "ARRAY: #{@results.to_s}"
end
RESULT: [1, 1, 1, 1]
INDEX: 0
ARRAY: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1], [1, 1]]
RESULT: [1, 1, 1, 1]
INDEX: 1
ARRAY: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1], [1, 1]]
RESULT: [1, 1, 1]
INDEX: 2
ARRAY: [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1]]
# @results == [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1]]
正如你可以看到,原本在索引2的元素已被删除。因为在迭代时正在修改@results
,所以索引3不再存在,和索引2已被分析。这就是为什么你不应该在遍历它时修改一个对象。
理想情况下,您要使用#delete_if
。类似于以!
结尾的方法,#delete_if
将根据块(作为参数)的条件修改数组(不返回结果的副本)。下面是你将如何实现方法:
def check_results(limit)
@results.delete_if { |arr| arr.length < limit }
end
@results = [ ['foo', 'bar'], ['bizz', 'bazz'], ['kaboom'] ]
check_results(2)
# => @results == [ ['foo', 'bar'], ['bizz', 'bazz'] ]
如果你不想修改@results
,那么我建议类似的方法,#reject
。同样,@results
将不会被修改,而是返回结果的副本。
def check_results(limit)
@results.reject { |arr| arr.length < limit }
end
@results = [ ['foo', 'bar'], ['bizz', 'bazz'], ['kaboom'] ]
check_results(2)
# => [ ['foo', 'bar'], ['bizz', 'bazz'] ]
# => @results == [ ['foo', 'bar'], ['bizz', 'bazz'], ['kaboom'] ]
你好。我编辑了我的答案,包括_why_您遇到问题。我包含调试语句。请看看它。我也为您的问题提供替代方案/解决方案:-) – onebree