我正在尝试从数组中删除奇数。
arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
def remove_odd_nums(arr)
for x in arr
if x % 2 == 0
arr.delete(x)
end
end
end
print remove_odd_nums(arr)
# [1, 3, 5, 7, 10]
我似乎无法使该程序正常工作。该方法适用于除最后一个数字以外的数字。我在做什么错了?
答案 0 :(得分:5)
您想删除奇数,但是您的程序正在删除偶数(x % 2 == 0
检查x是否为偶数)
方法1:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
arr.delete_if &:odd?
print arr
delete_if通过增加arr的索引进行迭代,并在对元素评估块&:odd?
之后立即删除该元素。换句话说,它将遍历数组中的每个元素,如果&:odd?
为true,则删除该元素。
&:odd?
:一个lambda函数,将一个对象传递给odd?
方法,如果该对象为奇数,则返回true。可以找到进一步的解释what is the functionality of "&: " operator in ruby?
请注意,方法1实际上是修改原始数组。为了创建一个新的无奇数数组,有...
方法2:
non_odds = arr.select{|i| not i.odd?}
答案 1 :(得分:3)
TL; DR:在迭代数组时不要修改它。
让我们通过在循环内打印x
和arr
的当前值来了解发生了什么:
def remove_odd_nums(arr)
for x in arr
p x: x, arr: arr # <- debug output
if x % 2 == 0
arr.delete(x)
end
end
end
remove_odd_nums([1, 2, 3, 4, 5, 6, 7, 8, 10])
输出:
{:x=>1, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>2, :arr=>[1, 2, 3, 4, 5, 6, 7, 8, 10]}
{:x=>4, :arr=>[1, 3, 4, 5, 6, 7, 8, 10]}
{:x=>6, :arr=>[1, 3, 5, 6, 7, 8, 10]}
{:x=>8, :arr=>[1, 3, 5, 7, 8, 10]}
前两个x
值符合预期:1
和2
。但是随后它继续前进到4
,跳过了3
。它还会跳过5
,7
和10
。但是为什么呢?
这是因为要在迭代时修改数组。将for
循环视为某人指向某个特定位置的元素。最初看起来像这样:
1 2 3 4 5 6 7 8 10 <- array
^ <- element
for
然后移至下一个元素:
1 2 3 4 5 6 7 8 10
^
此时x % 2 == 0
变为true,并且2
从数组中删除:
1 3 4 5 6 7 8 10
^
for
不知道此更改,只是继续前进到下一个元素:
1 3 4 5 6 7 8 10
^
这就是为什么我们无意中跳过了3
。 5
和7
也会发生同样的情况。
for
最终到达8
时:
1 3 5 7 8 10
^
它正在被删除:
1 3 5 7 10
^
和for
停止循环,因为它似乎已经到达数组的末尾。
答案 2 :(得分:2)
您好实用1只是为了阐明您为什么要破坏对象和数组?
如果您想过滤数组并仅选择even
个数字,则可以尝试Array#select和Integer#even的组合?方法助手
arr = arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# select all even numbers in an array
arr.select(&:even?) # shorthand for arr.select {|number| number.even? }
将返回偶数
[0] 2,
[1] 4,
[2] 6,
[3] 8,
[4] 10
来源:
Array#select https://apidock.com/ruby/Array/select
答案 3 :(得分:2)
Ruby具有出色的方法,可以根据块中的逻辑修改数组。
要获得仅包含奇数的数组,可以删除不符合测试的元素,或保留符合测试的数字。您可以返回一个新数组,也可以使用一种就地修改方法。
要删除不需要的值,请对新数组使用.reject或在适当的地方使用.reject!修改现有数组。
由于要删除,我们将在块内使用{|e| e%2!=0}
来表示奇数:
> [1,2,3,4,5,6,7,8,9,10].reject {|e| e%2!=0}
=> [2, 4, 6, 8, 10] # new array
> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.reject! {|e| e%2!=0}
=> [2, 4, 6, 8, 10] # arr modified in place
对于相同的结果,您也可以使用odd?
逻辑测试而不是阻止:
> [1,2,3,4,5,6,7,8,9,10].reject &:odd?
=> [2, 4, 6, 8, 10]
或者,您可以保留所需的值,而不保留其他值。您可以在块内使用{|e| e%2==0}
来获取偶数。或者,您可以使用&:even?
代替该块。
您可以使用.keep_if返回一个新数组:
> arr
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> [1,2,3,4,5,6,7,8,9,10].keep_if {|e| e%2==0}
=> [2, 4, 6, 8, 10] # new array.
或使用.select!进行修改:
> arr = [1, 2, 3, 4, 5, 6, 7, 8, 10]
=> [1, 2, 3, 4, 5, 6, 7, 8, 10]
> arr.select! {|e| e%2==0}
=> [2, 4, 6, 8, 10]
> arr
=> [2, 4, 6, 8, 10] # arr modified in place