Я знаю, що до регістру належить:
if (StringA == StringB) {
Так чи є оператор, який порівняє два рядки нечутливим чином?
~=
паралелі ==
як нечутливу до регістру версію.
Я знаю, що до регістру належить:
if (StringA == StringB) {
Так чи є оператор, який порівняє два рядки нечутливим чином?
~=
паралелі ==
як нечутливу до регістру версію.
Відповіді:
Спробуйте це:
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
if A$=B$ then goto 10
"
Кращий спосіб порівняти 2 рядки без урахування регістру літер є використання String.equals статичний метод , який визначає ордінала ігнорувати порівняння разі рядки. Це також найшвидший спосіб, набагато швидший, ніж перетворення рядків у нижній чи верхній регістр та порівняння їх після цього.
Я перевірив ефективність обох підходів, і порівняння рядкових випадків порядкового ігнорування було більш ніж у 9 разів швидше ! Це також надійніше, ніж перетворення рядків у нижній чи верхній регістр (ознайомтеся з проблемою турецького i). Тому завжди використовуйте метод String.Equals для порівняння рядків для рівності:
String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);
Якщо ви хочете виконати порівняння рядків, характерних для культури, ви можете використовувати наступний код:
String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);
Зверніть увагу, що другий приклад використовує логіку порівняння рядків у поточній культурі, що робить його повільніше порівняння зі «порядковим випадком ігнорування» у першому прикладі, тому якщо вам не потрібна якась специфічна для культури логіка порівняння рядків, і ви після максимальної продуктивності використовуйте порівняння «порядкового ігнорування випадку».
Для отримання додаткової інформації читайте повну історію в моєму блозі .
ToLower
або ToLowerInvariant
: вони створюють пам'ять просто для порівняння, і вони можуть не працювати, оскільки нові набори символів додаються до unicode. ToUpper
не вдається через турецьке «я», серед інших; немає жодних причин, чому б в ToLower
майбутньому не вийшло з подібних причин.
ToLower
чи ToLowerInvariant
методи, я просто хотів показати, наскільки ефективніший String.Equals
метод.
Існує ряд властивостей StringComparer
статичного класу, які повертають порівняльники для будь-якого типу чутливості до регістру, який ви хочете:
Наприклад, ви можете зателефонувати
StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)
або
StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)
Це трохи чистіше, ніж аргументи string.Equals
або string.Compare
перевантаження, які беруть StringComparison
аргументи.
System.Collections.CaseInsensitiveComparer
або
System.StringComparer.OrdinalIgnoreCase
або
if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {
але вам потрібно бути впевненим, що StringA не є нульовим. Тому, ймовірно, краще використовувати ту:
string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);
як запропонував Джон
EDIT: виправлено помилку
Можна використовувати
if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Оператор? НІ, але я думаю, ви можете змінити свою культуру, щоб порівняння рядків не залежно від регістру.
// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo
Я впевнений, що це змінить спосіб порівняння рядків оператором рівних.
Ось ідея спростити синтаксис:
public class IgnoreCase
{
private readonly string _value;
public IgnoreCase(string s)
{
_value = s;
}
protected bool Equals(IgnoreCase other)
{
return this == other;
}
public override bool Equals(object obj)
{
return obj != null &&
(ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
}
public override int GetHashCode()
{
return _value?.GetHashCode() ?? 0;
}
public static bool operator ==(IgnoreCase a, IgnoreCase b)
{
return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}
public static bool operator !=(IgnoreCase a, IgnoreCase b)
{
return !(a == b);
}
public static implicit operator string(IgnoreCase s)
{
return s._value;
}
public static implicit operator IgnoreCase(string s)
{
return new IgnoreCase(s);
}
}
Використовується як:
Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true
IgnoreCase
vs IgnoreCaseString
) та неоднозначно (Java вибирає неявне розпакування та неявне боксування, тому я вважаю, що це не буде працювати в Java з неявним відкиданням до рядка). І це створює обсяг пам'яті 2 нових об'єктів із виконанням дерева викликів для кожного порівняння, перескакуючи на кілька вкладених викликів методу для відображеного випадку використання. Однак, для більшості випадків продуктивність, мабуть, досить хороша.
Я так звик друкувати в кінці цих методів порівняння: , StringComparison.
Тому я зробив продовження.
namespace System
{ public static class StringExtension
{
public static bool Equals(this string thisString, string compareString,
StringComparison stringComparison)
{
return string.Equals(thisString, compareString, stringComparison);
}
}
}
Просто зауважте, що вам потрібно буде перевірити наявність "null" thisString
перед тим, як викликати доб.
string.Compare(string1, string2, true)
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {
Люди повідомляють, що ToUpperInvariant () швидше, ніж ToLowerInvariant ().
Інші відповіді тут цілком справедливі, але певний час, StringComparison.OrdinalIgnoreCase
а також використання потрібен певний час String.Compare
.
Я зашифрував простий метод розширення String, де ви могли вказати, чи порівняння є регістровим чи регістровим без букву з булевим - див. Наступну відповідь: