我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
当前回答
如果你想检查一个街区,你可以试试吗?还是全部?。
%w{ant bear cat}.any? {|word| word.length >= 3} #=> true
%w{ant bear cat}.any? {|word| word.length >= 4} #=> true
[ nil, true, 99 ].any? #=> true
有关详细信息,请参见Enumerable。
我的灵感来自于“评估数组中是否有任何项目”
其他回答
如果需要多次检查任何键,请将arr转换为哈希,然后检查O(1)
arr = ['Cat', 'Dog', 'Bird']
hash = arr.map {|x| [x,true]}.to_h
=> {"Cat"=>true, "Dog"=>true, "Bird"=>true}
hash["Dog"]
=> true
hash["Insect"]
=> false
Hash#has_key的性能?与Array#include相比?
Parameter Hash#has_key? Array#include Time Complexity O(1) operation O(n) operation Access Type Accesses Hash[key] if it Iterates through each element returns any value then of the array till it true is returned to the finds the value in Array Hash#has_key? call call
对于一次性检查,使用include?很好
有一个入口?正如@campeterson所指出的,ActiveSupport(Rails的一部分)中的方法。因此,在Rails中,或者如果您需要“active_support”,您可以编写:
'Unicorn'.in?(['Cat', 'Dog', 'Bird']) # => false
OTOH,没有in运算符或#in?尽管Ruby内核的顶级成员Yusuke Endoh之前就提出过这种方法,但这种方法在Ruby本身也是如此。
正如其他人所指出的,相反的方法包括?存在,对于所有枚举,包括Array、Hash、Set、Range:
['Cat', 'Dog', 'Bird'].include?('Unicorn') # => false
请注意,如果数组中有许多值,则将逐个检查这些值(即O(n)),而查找哈希值的时间将是恒定的(例如O(1))。例如,如果数组是常量,最好使用Set。例如:
require 'set'
ALLOWED_METHODS = Set[:to_s, :to_i, :upcase, :downcase
# etc
]
def foo(what)
raise "Not allowed" unless ALLOWED_METHODS.include?(what.to_sym)
bar.send(what)
end
快速测试显示,呼叫包括?在10个元素上调用Set比在等效数组上调用Set快3.5倍(如果找不到元素)。
最后一点:使用include时要小心?在Range上,有一些微妙之处,所以请参考文档并与封面进行比较?。。。
在下面尝试
(['Cat', 'Dog', 'Bird'] & ['Dog']).any?
还有另一种方法。
假设数组是[:edit,:update,:create,:show],那么可能就是七宗致命/宁静的罪。
还有一个想法,就是从某个字符串中提取一个有效的动作:
"my brother would like me to update his profile"
然后:
[ :edit, :update, :create, :show ].select{|v| v if "my brother would like me to update his profile".downcase =~ /[,|.| |]#{v.to_s}[,|.| |]/}
如果不想循环,则无法使用数组进行循环。您应该改用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)