我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
我有一个值“狗”和一个数组[“猫”、“狗”、“鸟”]。
如何在不循环的情况下检查数组中是否存在它?是否有一种简单的方法来检查该值是否存在?
当前回答
在下面尝试
(['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}[,|.| |]/}
有几个答案建议阵列#包括?,但有一个重要的警告:查看源代码,甚至是Array#include?确实执行循环:
rb_ary_includes(VALUE ary, VALUE item)
{
long i;
for (i=0; i<RARRAY_LEN(ary); i++) {
if (rb_equal(RARRAY_AREF(ary, i), item)) {
return Qtrue;
}
}
return Qfalse;
}
在不循环的情况下测试单词存在的方法是为数组构造一个trie。有很多trie实现(谷歌“ruby trie”)。我将在本例中使用随机trie:
a = %w/cat dog bird/
require 'rambling-trie' # if necessary, gem install rambling-trie
trie = Rambling::Trie.create { |trie| a.each do |e| trie << e end }
现在,我们已经准备好测试数组中各种单词的存在,而无需在O(log n)时间内对其进行循环,语法简单性与array#include?,使用子线Trie#include?:
trie.include? 'bird' #=> true
trie.include? 'duck' #=> false
检查是否存在
使用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
如果我们不想使用include?这也适用于:
['cat','dog','horse'].select{ |x| x == 'dog' }.any?
有一个入口?正如@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上,有一些微妙之处,所以请参考文档并与封面进行比较?。。。