Wiem, że rozróżniana jest wielkość liter:
if (StringA == StringB) {
Czy jest więc operator, który porównuje dwa ciągi w niewrażliwy sposób?
~=
równoległy ==
jako wersję bez uwzględniania wielkości liter.
Wiem, że rozróżniana jest wielkość liter:
if (StringA == StringB) {
Czy jest więc operator, który porównuje dwa ciągi w niewrażliwy sposób?
~=
równoległy ==
jako wersję bez uwzględniania wielkości liter.
Odpowiedzi:
Spróbuj tego:
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
if A$=B$ then goto 10
”
Najlepszym sposobem porównania 2 łańcuchów ignorujących wielkość liter jest użycie statycznej metody String.Equals , określającej porównanie ciągów liczb porządkowych ignorujących wielkość liter . Jest to również najszybszy sposób, znacznie szybszy niż konwersja ciągów znaków na małe lub duże litery i ich późniejsze porównywanie.
Przetestowałem wydajność obu podejść i porównanie ciągów znaków porządkowych ignorujących wielkość liter było ponad 9 razy szybsze ! Jest również bardziej niezawodny niż konwersja ciągów znaków na małe lub duże litery (sprawdź turecki problem i). Dlatego zawsze używaj metody String.Equals , aby porównać ciągi znaków dla równości:
String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);
Jeśli chcesz przeprowadzić porównanie ciągów specyficznych dla kultury, możesz użyć następującego kodu:
String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);
Zwróć uwagę, że w drugim przykładzie użyto logiki porównywania ciągów bieżącej kultury, co powoduje, że jest ona wolniejsza niż porównanie „porządkowego ignorowania wielkości liter” w pierwszym przykładzie, więc jeśli nie potrzebujesz żadnej logiki porównywania ciągów specyficznej dla kultury i jesteś po osiągnięciu maksymalnej wydajności użyj porównania „porządkowa ignoruj wielkość liter”.
Aby uzyskać więcej informacji, przeczytaj całą historię na moim blogu .
ToLower
ani ToLowerInvariant
: tworzą pamięć tylko w celu wykonania porównania i mogą się nie powieść, gdy nowe zestawy znaków zostaną dodane do Unicode. ToUpper
zawodzi z powodu m.in. tureckiego „i”; nie ma powodu, dla którego ToLower
nie zawiedzie w przyszłości z podobnych powodów.
ToLower
ani ToLowerInvariant
metod, chciałem tylko pokazać, o ile wydajniejsza jest ta String.Equals
metoda.
Istnieje wiele właściwości w StringComparer
klasie statycznej, które zwracają elementy porównujące dla dowolnego typu rozróżniania wielkości liter:
Na przykład możesz zadzwonić
StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)
lub
StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)
Jest trochę czystszy niż przeciążenia string.Equals
lub, string.Compare
które przyjmują StringComparison
argument.
System.Collections.CaseInsensitiveComparer
lub
System.StringComparer.OrdinalIgnoreCase
lub
if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {
ale musisz mieć pewność, że StringA nie jest null. Więc prawdopodobnie lepiej użyć:
string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);
jak zasugerował John
EDYCJA: poprawiono błąd
Możesz użyć
if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Operator? NIE, ale myślę, że możesz zmienić swoją kulturę, aby w porównaniu ciągów nie była rozróżniana wielkość liter.
// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo
Jestem przekonany, że zmieni to sposób porównywania ciągów znaków przez operator równości.
Oto pomysł na uproszczenie składni:
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);
}
}
Użyteczne jak:
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
) i niejednoznaczna (Java wybiera niejawne rozpakowywanie vs niejawne pakowanie, więc uważam , że nie zadziałaoby to w Javie z niejawnym rzutowaniem z powrotem na ciąg). Tworzy to narzut pamięci na 2 nowe obiekty, a wykonanie drzewa wywołań dla każdego porównania przeskakuje do kilku zagnieżdżonych wywołań metod dla wyświetlanego przypadku użycia. To powiedziawszy, w większości przypadków wydajność jest prawdopodobnie wystarczająco dobra.
Jestem przyzwyczajony do pisania na końcu tych metod porównawczych: , StringComparison.
Więc zrobiłem rozszerzenie.
namespace System
{ public static class StringExtension
{
public static bool Equals(this string thisString, string compareString,
StringComparison stringComparison)
{
return string.Equals(thisString, compareString, stringComparison);
}
}
}
Zwróć uwagę, że thisString
przed wywołaniem rozszerzenia ext.
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {
Ludzie zgłaszają, że ToUpperInvariant () jest szybsze niż ToLowerInvariant ().
Inne odpowiedzi są tutaj całkowicie poprawne, ale w jakiś sposób wpisanie StringComparison.OrdinalIgnoreCase
i użycie zajmuje trochę czasu String.Compare
.
Zakodowałem prostą metodę rozszerzenia String, w której możesz określić, czy porównanie ma rozróżniać wielkość liter, czy bez sensu z wartością logiczną - zobacz następującą odpowiedź: