Я знаю, что следующее учитывает регистр:
if (StringA == StringB) {
Так есть ли оператор, который будет сравнивать две строки нечувствительным образом?
~=
параллели ==
в качестве версии без учета регистра.
Я знаю, что следующее учитывает регистр:
if (StringA == StringB) {
Так есть ли оператор, который будет сравнивать две строки нечувствительным образом?
~=
параллели ==
в качестве версии без учета регистра.
Ответы:
Попробуй это:
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
if A$=B$ then goto 10
"
Лучший способ сравнить 2 строки, игнорируя регистр букв, - это использовать статический метод String.Equals, определяющий порядковое игнорирование сравнения строк регистра. Это также самый быстрый способ, гораздо быстрее, чем преобразование строк в нижний или верхний регистр и сравнение их после этого.
Я проверил производительность обоих подходов, и сравнение строк в регистре игнорирования было более чем в 9 раз быстрее ! Это также более надежно, чем преобразование строк в нижний или верхний регистр (см. Проблему Turkish i). Поэтому всегда используйте метод String.Equals для сравнения строк на равенство:
String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);
Если вы хотите выполнить сравнение строк для конкретной культуры, вы можете использовать следующий код:
String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);
Обратите внимание, что во втором примере используется логика сравнения строк текущей культуры, что делает его медленнее, чем сравнение «порядкового игнорирования регистра» в первом примере, поэтому если вам не нужна логика сравнения строк для конкретной культуры, и вы после максимальной производительности используйте сравнение «порядковый номер игнорирования».
Для получения дополнительной информации прочитайте полную историю в моем блоге .
ToLower
или ToLowerInvariant
: они создают память только для выполнения сравнения, и они могут потерпеть неудачу, когда новые наборы символов добавляются в юникод. 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);
как предположил Джон
РЕДАКТИРОВАТЬ: исправлена ошибка
Ты можешь использовать
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
Я уверен, что это изменит способ сравнения строк оператором equals.
Вот идея упростить синтаксис:
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
против 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);
}
}
}
Просто отметьте, что вам нужно будет проверить наличие нуля thisString
до вызова ext.
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {
Люди сообщают, что ToUpperInvariant () работает быстрее, чем ToLowerInvariant ().
Другие ответы здесь полностью действительны, но каким-то образом требуется некоторое время, чтобы напечатать, StringComparison.OrdinalIgnoreCase
а также использовать String.Compare
.
Я написал простой метод расширения String, в котором вы можете указать, является ли сравнение чувствительным к регистру или бессмысленным с логическим значением - см. Следующий ответ: