我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
当前回答
检查是否存在
使用include?
例子:
arr = [1, 2, 3]
arr.include?(1) -> true
arr.include?(4) -> false
支票不存在
使用排除?
例子:
arr = %w(vietnam china japan)
arr.exclude?('usa') -> true
arr.exclude?('china') -> false
其他回答
还有一种方法可以做到这一点:
arr = ['Cat', 'Dog', 'Bird']
e = 'Dog'
present = arr.size != (arr - [e]).size
如果不想循环,则无法使用数组进行循环。您应该改用Set。
require 'set'
s = Set.new
100.times{|i| s << "foo#{i}"}
s.include?("foo99")
=> true
[1,2,3,4,5,6,7,8].to_set.include?(4)
=> true
设置在内部像Hashes一样工作,因此Ruby不需要在集合中循环查找项,因为顾名思义,它会生成键的哈希值,并创建内存映射,以便每个哈希值指向内存中的某个点。前面的示例使用Hash完成:
fake_array = {}
100.times{|i| fake_array["foo#{i}"] = 1}
fake_array.has_key?("foo99")
=> true
缺点是Set和Hash键只能包含唯一的项,如果你添加了很多项,Ruby将不得不在一定数量的项之后重新散列整个项,以构建适合更大键空间的新映射。有关这方面的更多信息,我建议您观看“MountainWest RubyConf 2014-Nathan Long自制哈希中的大O”。
这里有一个基准:
require 'benchmark'
require 'set'
array = []
set = Set.new
10_000.times do |i|
array << "foo#{i}"
set << "foo#{i}"
end
Benchmark.bm do |x|
x.report("array") { 10_000.times { array.include?("foo9999") } }
x.report("set ") { 10_000.times { set.include?("foo9999") } }
end
结果是:
user system total real
array 7.020000 0.000000 7.020000 ( 7.031525)
set 0.010000 0.000000 0.010000 ( 0.004816)
如果要返回值而不仅仅是true或false,请使用
array.find{|x| x == 'Dog'}
如果列表中存在“Dog”,则返回该值,否则为零。
如果你不想使用include?您可以首先将元素包装在数组中,然后检查包装的元素是否等于数组和包装的元素的交集。这将返回一个基于相等的布尔值。
def in_array?(array, item)
item = [item] unless item.is_a?(Array)
item == array & item
end
您正在查找包含项?:
>> ['Cat', 'Dog', 'Bird'].include? 'Dog'
=> true