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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9333952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:46:39  来源:igfitidea点击:

Case-insensitive Array#include?

rubystring

提问by Just a learner

I want to know what's the best way to make the String.include?methods ignore case. Currently I'm doing the following. Any suggestions? Thanks!

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

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

Edit: How about Array.include?. All elements of the array are strings.

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

回答by Phrogz

Summary

概括

If you are only going to test a single word against an array, or if the contents of your array changes frequently, the fastest answer is Aaron's:

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

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

If you are going to test many words against a static array, it's far better to use a variation of farnoy's answer: create a copy of your array that has all-lowercase versions of your words, and use include?. (This assumes that you can spare the memory to create a mutated copy of your array.)

如果要针对静态数组测试多个单词,最好使用 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 )

Even better, create a Setfrom your array.

更好的是,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 )

My original answer below is a very poor performer and generally not appropriate.

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

Benchmarks

基准

Following are benchmarks for looking for 1,000 words with random casing in an array of slightly over 100,000 words, where 500 of the words will be found and 500 will not.

以下是在略高于 100,000 个单词的数组中查找 1,000 个随机大小写单词的基准,其中 500 个单词会被找到,500 个不会。

  • The 'regex' text is my answer here, using any?.
  • The 'casecmp' test is Arron's answer, using any?from my comment.
  • The 'downarray' test is farnoy's answer, re-creating a new downcased array for each of the 1,000 tests.
  • The 'downonce' test is farnoy's answer, but pre-creating the lookup array once only.
  • The 'set_once' test is creating a Setfrom the array of downcased strings, once before testing.
  • “正则表达式”文本是我在这里的答案,使用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)

If you can create a single downcased copy of your array once to perform many lookups against, farnoy's answer is the best (assuming you mustuse an array). If you can create a Set, though, do that.

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

If you like, examine the benchmarking code.

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



Original Answer

原答案

I (originally said that I)would personally create a case-insensitive regex (for a string literal) and use that:

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

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

Using any?can be slightly faster than grepas it can exit the loop as soon as it finds a single match.

使用any?可能比grep它在找到单个匹配项后立即退出循环稍快。

回答by farnoy

For an array, use:

对于数组,请使用:

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

Regexps are very slow and should be avoided.

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

回答by Aaron McIver

You can use casecmpto do your comparison, ignoring case.

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

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

回答by johannes

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

回答by Konda Reddy R

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

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

where map!changes my_array, mapinstead returns a new array.

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

回答by 6ft Dan

To farnoy in my case your example doesn't work for me. I'm actually looking to do this with a "substring" of any.

在我的情况下,你的例子对我不起作用。我实际上希望用 any 的“子字符串”来做到这一点。

Here's my test case.

这是我的测试用例。

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

Your case works with an exact case-insensitive match.

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

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

I'm still experimenting with the other suggestions here.

我仍在尝试这里的其他建议。

---EDIT INSERT AFTER HERE---

---在此之后编辑插入---

I found the answer. Thanks to 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)}
=> []