Jak porównać ciągi znaków ignorując wielkość liter

171

Chcę applei Appleporównanie być true. Obecnie

"Apple" == "Apple"  # returns TRUE
"Apple" == "APPLE"  # returns FALSE
Steven
źródło

Odpowiedzi:

273

Szukasz casecmp. Zwraca, 0jeśli dwa ciągi są równe, bez rozróżniania wielkości liter.

str1.casecmp(str2) == 0

"Apple".casecmp("APPLE") == 0
#=> true

Alternatywnie możesz przekonwertować oba ciągi na małe litery ( str.downcase) i porównać je pod kątem równości.

molf
źródło
19
Z moich testów porównawczych casecmp jest co najmniej dwa razy szybszy niż metoda downcase
Jacob
77
casecmp: Głupie imię dla CASE- w wrażliwego metodą porównania ?!
Zabba,
4
@Zabba: Winić ludzi libc: pubs.opengroup.org/onlinepubs/9699919799/functions/ ...
mu jest za krótkie
17
Jeśli podoba Ci się za pomocą słów, można wymienić == 0zzero?
Andrew Grimm
3
Jeśli używasz Rubocop, właściwy sposób, aby nie narzekać, to "Apple".casecmp("APPLE").zero?Ale osobiście podoba mi się odpowiedź Andresa poniżej, która używa.casecmp?
8bithero
45

W Rubim 2.4.0 masz:casecmp?(other_str) → true, false, or nil

"abcdef".casecmp?("abcde")     #=> false
"aBcDeF".casecmp?("abcdef")    #=> true
"abcdef".casecmp?("abcdefg")   #=> false
"abcdef".casecmp?("ABCDEF")    #=> true

Tutaj masz więcej informacji

Andres
źródło
3
Dobre ulepszenie metody, ale jest to jedna z najmniej "brzmiących rubinowo" metod, jakie kiedykolwiek widziałem. Wydaje mi się, że używam Java z tymi casecmpśmieciami.
Joshua Pinter
Szczerze sugeruję, abyś "aBcDeF".downcase == "abcdef"zamiast tego używał . Znacznie bardziej czytelne, a korzyści wynikające z używania casecmpsą wyeliminowane w Ruby 2.4+.
Joshua Pinter
Czekaj, jaka byłaby różnica między falsei nildla takiego API ...
Trejkaz
Zgodnie z dokumentacją zwracane jest nil, gdy parametr other_str nie jest ciągiem znaków
ramblex
8

W przypadku, gdy musisz porównać łańcuchy UTF-8 ignorując wielkość liter:

>> str1 = "Мария"
=> "Мария"
>> str2 = "мария"
=> "мария"
>> str1.casecmp(str2) == 0
=> false
>> require 'active_support/all'
=> true
>> str1.mb_chars.downcase.to_s.casecmp(str2.mb_chars.downcase.to_s) == 0
=> true

Działa to w ten sposób w Rubim 2.3.1 i wcześniejszych wersjach.

Aby uzyskać mniejszy rozmiar pamięci, możesz wybrać string/multibyte:

require 'active_support'
require 'active_support/core_ext/string/multibyte'

Edycja , Ruby 2.4.0:

>> str1.casecmp(str2) == 0
=> false

Więc casecmpnie działa w 2.4.0; Jednak w 2.4.0 można ręcznie porównać łańcuchy UTF-8 bez active_supportklejnotu:

>> str1.downcase == str2.downcase
=> true
Cegła suszona na słońcu
źródło
5

casecmp i zero? to metody wbudowane w rubiny. casecmp zwraca 0, jeśli dwa łańcuchy są równe, bez rozróżniania wielkości liter i zero? sprawdza wartość zerową (== 0)

str1.casecmp(str2).zero?
Sivalingam
źródło
Tak powiedział mi mój moduł sprawdzania stylu i podoba mi się to, ponieważ jest bardziej przejrzysty niż porównanie z dosłownym 0, zwłaszcza gdy jest zagnieżdżony z bardziej złożonym warunkiem.
Amos Shapira
5

Dla Ruby 2.4 działa dobrze casecmp? dla ciągów utf-8 (mb_chars nie są potrzebne):

2.4.1 :062 > 'строка1'.casecmp?('СтроКа1')
 => true

ale casecmp nie działa dla utf-8:

2.4.1 :062 > 'строка1'.casecmp('СтроКА1')
 => 1
2.4.1 :063 > 'string1'.casecmp('StrInG1')
 => 0
Sergio Belevskij
źródło