Arrays Ruby无法删除数组中的元素
对于下面的代码片段。Arrays Ruby无法删除数组中的元素,arrays,ruby,Arrays,Ruby,对于下面的代码片段。 我想从数组中删除等于3的元素。 但是代码只删除了第一个元素。调试代码时, 我发现迭代器只在数组中循环一次而不是两次。 我不确定是什么导致了这个问题。任何帮助都将不胜感激 nums = [3,3] def remove_element(nums, val) nums.each_with_index do |num,index| if num == val nums.slice!(index) end en
我想从数组中删除等于3的元素。 但是代码只删除了第一个元素。调试代码时,
我发现迭代器只在数组中循环一次而不是两次。
我不确定是什么导致了这个问题。任何帮助都将不胜感激
nums = [3,3]
def remove_element(nums, val)
nums.each_with_index do |num,index|
if num == val
nums.slice!(index)
end
end
nums.length
end
remove_element(nums,3)
正如@steenslag所指出的,
delete
方法将实现您想要的功能:
n = [1,2,3,3,4,5,6,3,4,5,3,2,1,8]
n.delete(3)
n
返回:[1,2,4,5,6,4,5,2,1,8]
值得一看的是,除了您的代码之外,还有以下替代方案:
nums = [3,3]
def remove_element(nums, val)
nums.each_with_index do |num,index|
nums_before_slice = nums.clone
if num == val
sliced = nums.slice!(index)
end
puts "nums: #{nums_before_slice}, index: #{index}, sliced: #{sliced.inspect}"
end
end
remove_element(nums,3)
puts "Result: #{nums.inspect}"
输出将是:
nums: [3, 3], index: 0, sliced: 3
Result: [3]
如您所见,迭代只发生一次,因为在进行第二次迭代之前,第二个元素已被删除
将该结果与此版本的代码进行比较:
nums = [3,3]
def remove_element(nums, val)
nums.clone.each_with_index do |num,index|
nums_before_slice = nums.clone
if num == val
sliced = nums.slice!(index)
end
puts "nums: #{nums_before_slice}, index: #{index}, sliced: #{sliced.inspect}"
end
end
remove_element(nums,3)
puts "Result: #{nums.inspect}"
其结果是:
nums: [3, 3], index: 0, sliced: 3
nums: [3], index: 1, sliced: nil
Result: [3]
现在,这将在原始
nums
的副本上运行迭代,但结果与第二次迭代相同-没有要删除的第二个元素 正如正确评论的那样,您在迭代时修改了数组,因此它删除了第一个元素,并结束了迭代。如果您在nums.内放置一个打印语句,每个带有索引的循环,您将看到它只打印一次
删除图元的更好方法是使用以下拒绝方法:
nums.reject!{|item| item == 3}
方法呢
还是
UPD
require 'benchmark'
array = Array.new(100000) { rand(5) }
Benchmark.bm do |x|
x.report("delete: ") { array.delete(5) }
x.report("delete_if: ") { array.delete_if { |e| e == 5 } }
x.report("reject: ") { array.reject! { |e| e == 5 } }
end
# user system total real
# delete: 0.000000 0.000000 0.000000 ( 0.004230)
# delete_if: 0.010000 0.000000 0.010000 ( 0.006387)
# reject: 0.010000 0.000000 0.010000 ( 0.007543)
不要在迭代数组时试图修改它。枚举数发疯了。不要修改你正在迭代的同一个数组。@mudasobwa谢谢,你能告诉我原因吗?这个问题在这个网站上已经被问过很多次了。第一次迭代在索引0处。您将删除该元素。现在,过去位于索引1的元素位于索引0,过去位于索引2的元素位于索引1,依此类推。下一次迭代在索引1处,它是过去位于索引2处的元素。看见已跳过以前位于索引1的元素。在您的情况下,整个过程在1次迭代后已经停止,因为在第一次迭代后,数组的大小是1,因此在第二次迭代中没有可以访问的索引1。@JörgWMittag非常有用谢谢,您能告诉我为什么在删除第一次迭代后迭代器停止吗element@MarcoSong,我认为迭代器在内部一直在寻找下一个要迭代的项,当您删除第一个元素时,迭代器在第二个元素上,但它没有找到下一个元素并返回。检查这里:谢谢你的帮助。非常容易理解。n.delete(3)
@steenslag是-删除是另一个(可能更好)选项。是的,我从leetcode看到了这个解决方案。它真的很强大而且干净。但是代码运行速度不是很快,我认为delete方法的工作方式可能不是很有效,也不是很慢all@MarcoSong我很高兴:)下次您可以使用upd中的示例检查方法速度之间的差异:)
nums = [3,3]
def remove_element(nums, val)
nums.delete_if { |element| element == val }
nums.length
end
remove_element(nums, 3)
#=> 0
require 'benchmark'
array = Array.new(100000) { rand(5) }
Benchmark.bm do |x|
x.report("delete: ") { array.delete(5) }
x.report("delete_if: ") { array.delete_if { |e| e == 5 } }
x.report("reject: ") { array.reject! { |e| e == 5 } }
end
# user system total real
# delete: 0.000000 0.000000 0.000000 ( 0.004230)
# delete_if: 0.010000 0.000000 0.010000 ( 0.006387)
# reject: 0.010000 0.000000 0.010000 ( 0.007543)