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

我想知道使Array.include?方法忽略大小写的最佳方法是什么。 目前,我正在执行以下操作。 有什么建议? 谢谢!

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

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

Just a learner asked 2020-06-29T23:33:33Z
6个解决方案
57 votes

摘要

如果您仅要针对数组测试单个单词,或者数组的内容频繁更改,则最快的答案是Aaron:

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

如果要针对静态数组测试许多单词,最好使用变种的farnoy答案:创建包含单词全小写版本的数组副本,并使用any?。(这假定您可以 保留内存以创建数组的变异副本。)

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

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

更好的是,从阵列中创建any?

# 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个单词的数组中查找带有随机大小写的1,000个单词的基准,其中将找到500个单词,而不会找到500个单词。

  • “ regex”文本是我在这里的答案,使用any?
  • “ casecmp”测试是Arron的答案,使用我的评论中的any?
  • “ downarray”测试是Farnoy的答案,可以为1,000个测试中的每一个重新创建一个新的缩减大小写的数组。
  • “ downonce”测试是Farnoy的答案,但只能预先创建一次查找数组。
  • “ set_once”测试是在测试前从一组小写的字符串创建any?
                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的答案是最好的(假设您必须使用数组)。 但是,如果您可以创建any?,请执行此操作。

如果您愿意,请检查基准测试代码。


原始答案

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

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快一点,因为一旦找到单个匹配项,它便可以退出循环。

Phrogz answered 2020-06-29T23:34:59Z
11 votes

对于数组,请使用:

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

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

farnoy answered 2020-06-29T23:35:23Z
7 votes

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

"abcdef".casecmp("abcde")     #=> 1
"aBcDeF".casecmp("abcdef")    #=> 0
"abcdef".casecmp("abcdefg")   #=> -1
"abcdef".casecmp("ABCDEF")    #=> 0
Aaron McIver answered 2020-06-29T23:35:43Z
3 votes
class String
    def caseinclude?(x)
        a.downcase.include?(x.downcase)
    end
end
johannes answered 2020-06-29T23:35:58Z
3 votes

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

其中map!更改了my_array,而map则返回了一个新数组。

Konda Reddy R answered 2020-06-29T23:36:22Z
-2 votes

令我烦恼的是,您的榜样对我不起作用。 我实际上正在寻找使用任何“子字符串”做到这一点。

这是我的测试用例。

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)}
=> []
6ft Dan answered 2020-06-29T23:37:04Z
translate from https://stackoverflow.com:/questions/9333952/case-insensitive-arrayinclude