不区分大小写的数组#include?

时间:2012-02-17 19:10:44

标签: ruby string

我想知道使String.include?方法忽略大小写的最佳方法是什么。目前我正在做以下事情。有什么建议?谢谢!

a = "abcDE"
b = "CD"
result = a.downcase.include? b.downcase

编辑: Array.include?怎么样?数组的所有元素都是字符串。

6 个答案:

答案 0 :(得分:56)

摘要

如果您只是针对数组测试单个单词,或者数组内容经常更改,那么最快的答案就是Aaron:

array.any?{ |s| s.casecmp(mystr)==0 }

如果要针对静态数组测试多个单词,最好使用farnoy答案的变体:创建一个包含单词全小写版本的数组副本,然后使用include? 。 (这假设您可以节省内存来创建阵列的变异副本。)

# Do this once, or each time the array changes
downcased = array.map(&:downcase)

# Test lowercase words against that array
downcased.include?( mystr.downcase )

更好的是,从数组中创建Set

# Do this once, or each time the array changes
downcased = Set.new array.map(&:downcase)

# Test lowercase words against that array
downcased.include?( mystr.downcase )

我在下面的原始答案表现非常糟糕,通常不合适。

基准

下面是在一个略超过100,000个单词的数组中查找带有随机大小写的1000个单词的基准,其中500个单词将被找到,500个单词将不会。

  • “正则表达式”文字是我的答案,使用any?
  • 'casecmp'测试是Arron的答案,在我的评论中使用any?
  • 'downarray'测试是farnoy的答案,为1,000次测试中的每次测试重新创建一个新的下行阵列。
  • 'downonce'测试是farnoy的答案,但只预先创建一次查找数组。
  • 'set_once'测试是在测试之前从下层字符串数组中创建Set
                user     system      total        real
regex      18.710000   0.020000  18.730000 ( 18.725266)
casecmp     5.160000   0.000000   5.160000 (  5.155496)
downarray  16.760000   0.030000  16.790000 ( 16.809063)
downonce    0.650000   0.000000   0.650000 (  0.643165)
set_once    0.040000   0.000000   0.040000 (  0.038955)

如果您可以创建一个单个下载的数组副本一次以执行许多查找,farnoy的答案是最好的(假设您必须使用数组)。但是,如果您可以创建Set,请执行此操作。

如果您愿意,examine the benchmarking code


原始答案

(最初说我)会亲自创建一个不区分大小写的正则表达式(对于字符串文字)并使用它:

re = /\A#{Regexp.escape(str)}\z/i # Match exactly this string, no substrings
all = array.grep(re)              # Find all matching strings…
any = array.any?{ |s| s =~ re }   #  …or see if any matching string is present

使用any?可能会比grep略快,因为它可以在找到单个匹配后立即退出循环。

答案 1 :(得分:11)

对于数组,请使用:

array.map(&:downcase).include?(string)

正则表达式非常慢,应该避免使用。

答案 2 :(得分:7)

您可以使用casecmp进行比较,忽略大小写。

"abcdef".casecmp("abcde")     #=> 1
"aBcDeF".casecmp("abcdef")    #=> 0
"abcdef".casecmp("abcdefg")   #=> -1
"abcdef".casecmp("ABCDEF")    #=> 0

答案 3 :(得分:3)

class String
    def caseinclude?(x)
        a.downcase.include?(x.downcase)
    end
end

答案 4 :(得分:3)

  

my_array.map {|!Ç| c.downcase.strip}

map!更改my_array,而map会返回一个新数组。

答案 5 :(得分:-2)

就我而言,你的例子对我不起作用。我实际上是想用任何一个“子串”做到这一点。

这是我的测试用例。

x = "<TD>", "<tr>", "<BODY>"
y = "td"
x.collect { |r| r.downcase }.include? y
=> false
x[0].include? y
=> false
x[0].downcase.include? y
=> true

您的案例使用完全不区分大小写的匹配。

a = "TD", "tr", "BODY"
b = "td"
a.collect { |r| r.downcase }.include? b
=> true

我还在尝试其他建议。

---此后编辑插入---

我找到了答案。感谢Drew Olsen

var1 = "<TD>", "<tr>","<BODY>"
=> ["<TD>", "<tr>", "<BODY>"]
var2 = "td"
=> "td"
var1.find_all{|item| item.downcase.include?(var2)}
=> ["<TD>"]
var1[0] = "<html>"
=> "<html>"
var1.find_all{|item| item.downcase.include?(var2)}
=> []