我正在尝试创建一个方法来过滤包含正整数和字符串的数组,只留下整数,但奇怪的是我的代码不起作用。
def filter_list(l)
l.map { |items| items.is_a?(Integer) ? items : l.delete(items) }
end
filter_list([1,2,'a','b'])
从理论上讲,我的代码是有效的,因为如果我将items
和l.delete(items)
替换为'true'和'false'整数和字符串正在被正确替换
[true, true, false, false]
但是,保持items : l.delete(items)
它会让我回复
[1, 2, "a"] or sometimes [1, 2, "b"]
所以只删除一个。如何改变我的方法只返回整数?
答案 0 :(得分:4)
您的代码不起作用,因为在迭代同一个数组时,使用l.delete
从数组中删除元素。
想象一下,你走了一个包含4个元素的数组,同时,有人会改变数组中元素的数量及其位置。
我认为您正在寻找Array#select
:
array = [1, 2, 'a', 'b']
array.select { |element| element.is_a?(Integer) }
#=> [1, 2]
答案 1 :(得分:1)
如果您的项目不是整数,那么您的问题是您正在更改数组map
ping。
当您map
首次访问元素'a'
时,它会调用l.delete('a')
(返回'a'
)。这意味着'l'
不再是您的map
结束的初始数组。您的数组[1, 2, 'a', 'b']
现在包含l
。
[1, 2, 'b']
我不确定map
的确切实现,但我想现在数组已被更改,只包含三个而不是四个元素,map
不会查看最终'b'
在你的数组中。
我们假设你有一个数组a = [1, 2, 'a', 'b']
。
第一次拨打filter_list(a)
时,它会返回[1, 2, 'a']
。如果您现在打印a
,您将获得已更改数组的内容:[1, 2, 'b']
。为什么这与函数调用的结果不同?因为map会创建一个包含map
的返回值的新数组(而delete
会返回已删除的值,该值会在第一次调用中生成'a'
)。但是,当我们的数组'a'
中删除了a
时,我们数组的结果为[1, 2, 'b']
。
下次您filter_list(a)
map
[1, 2, 'b']
以上delete
。这导致第二次调用'b'
,返回map
。因此[1, 2, 'b']
返回包含filter_list
的新数组。在第二次调用a
之后,您再次更改了输入数组,以便我们的数组[1, 2]
现在只包含filter_list(a)
。
如果您再次致电[1, 2]
,结果会得到a
,select
将不会再次更改,因为数组中没有要删除的字符串。
您应该始终小心改变您的输入数据,因为它可能具有(并且在这种情况下)有意外的副作用。
更好的替代方案是使用Ruby的a = [1, 2, 'a', 'b']
a.select { |element| element.is_a?(Integer) }
方法(这是一种过滤方法)(https://ruby-doc.org/core-2.4.0/Array.html#method-i-select):
Public Class WorkStationDetails<br><br>
Property CountryId As Integer<br>
Property CountryName As String<br>
Property TotalWrkStn As Integer<br>
Property ExistingWrkStn As Integer<br>
Property RemainingWrkStn As Integer<br><br>
End Class
Dim WrkStnDtl As List(Of WorkStationDetails)
Dim FilterWrkStnDtl As List(Of WorkStationDetails)
Dim Numbers As String()
Numbers = "1,5,6,2,9".Split(",")
For i As Integer = 0 To Numbers.Length - 1
FilterWrkStnDtl.AddRange(WrkStnDtl.FindAll(Function(p) (p.CountryId = Numbers(i))))
Next
答案 2 :(得分:1)
试试这个:
a = [1, 2, 3.4, 'a', 'b', [:c], { d: 1 }]
a.grep Integer #=> [1, 2]
a.grep Float #=> [3.4]
a.grep Numeric #=> [1, 2, 3.4]
a.grep String #=> ['a', 'b']
a.grep Array #=> [[:c]]
a.grep Hash #=> [{ :d => 1 }]
请参阅Enumerable#grep。
答案 3 :(得分:0)
.delete(items)
返回映射到数组的items
。
在你的控制台中,
arr = [1,2,'a','b']
arr.delete('b')
# => 'b'
arr
# => [1, 2, 'a']
因此,删除也有效,但它返回已删除的元素,因此无法映射,因为.map
创建了一个包含块返回值的数组。
如果您想使用.delete
,那么
def filter_list(l)
l.dup.each{ |e| l.delete(e) unless e.is_a?(Integer) }
l
end
效率低下,试试
l.select { |items| items.is_a?(Integer) }
答案 4 :(得分:0)
grep
是正确的答案。
如果要按类对元素进行分组,可以写:
strings, integers = [1,2,'a','b'].group_by(&:class).values_at(String, Fixnum)
strings
# => ["a", "b"]
integers
# => [1, 2]
答案 5 :(得分:0)
如果您仍想使用您编写的代码,您可以执行以下操作:
def filter_list(l)
i = l.length
while i > 0
l.map { |items| items.is_a?(Integer) ? items : l.delete(items) }
i -= 1
end
l
end
filter_list([1, 2, 'a', 'b', 3, 'duh', 'isitover?']) # will return [1, 2, 3]