Верхний и нижний регистр - PullRequest
       32

Верхний и нижний регистр

78 голосов
/ 24 октября 2008

При выполнении сравнения без учета регистра более эффективно преобразовывать строку в верхний или нижний регистр? Это вообще имеет значение?

В этом посте SO предлагается *1004*, что C # более эффективен с ToUpper, потому что "Microsoft оптимизировала его таким образом". Но я также прочитал этот аргумент , что преобразование ToLower против ToUpper зависит от того, что в ваших строках больше, и что обычно строки содержат больше символов нижнего регистра, что делает ToLower более эффективным.

В частности, я хотел бы знать:

  • Есть ли способ оптимизировать ToUpper или ToLower так, чтобы один был быстрее другого?
  • Быстрее ли сравнивать строки в верхнем или нижнем регистре без учета регистра и почему?
  • Существуют ли какие-либо среды программирования (например, C, C #, Python и т. Д.), В которых один случай явно лучше другого и почему?

Ответы [ 10 ]

88 голосов
/ 24 октября 2008

Преобразование в верхний или нижний регистр для сравнения без учета регистра некорректно из-за «интересных» особенностей некоторых культур, в частности Турции. Вместо этого используйте StringComparer с соответствующими параметрами.

В MSDN есть замечательные рекомендации по обработке строк. Вы также можете проверить, что ваш код проходит тест Турции .

РЕДАКТИРОВАТЬ: Обратите внимание на комментарий Нейла около порядкового сравнения без учета регистра. Все это царство довольно темное: (

22 голосов
/ 03 января 2013

С Microsoft на MSDN:

Рекомендации по использованию строк в .NET Framework

Рекомендации по использованию строк

Почему? От Microsoft :

Нормализация строк в верхний регистр

Существует небольшая группа символов, которые при преобразовании в нижний регистр не могут совершать поездки в оба конца.

Что является примером такого персонажа, который не может совершить путешествие туда и обратно?

  • Начало : символ греческого Ро (U + 03f1) & # x03f1;
  • Прописные буквы: Заглавная греческая Ро (U + 03a1) & # x03a1;
  • Строчные: Маленький греческий Ро (U + 03c1) & # x03c1;

& # x03f1; , & # x03a1; , & # x03c1;

Вот почему, если вы хотите выполнять сравнение без учета регистра, вы переводите строки в верхний, а не в нижний регистр.

18 голосов
/ 24 октября 2008

Согласно MSDN более эффективно передавать строки и указывать сравнение для игнорирования регистра:

String.Compare (strA, strB, StringComparison.OrdinalIgnoreCase) эквивалентно (, но быстрее ) вызова

String.Compare (ToUpperInvariant (strA), ToUpperInvariant (strB), StringComparison.Ordinal).

Эти сравнения все еще очень быстрые.

Конечно, если вы сравниваете одну строку снова и снова, это может не сработать.

12 голосов
/ 24 октября 2008

Исходя из того, что строки имеют тенденцию иметь больше строчных букв, теоретически ToLower должен быть быстрее (много сравнений, но мало назначений).

В C, или при использовании индивидуально доступных элементов каждой строки (таких как строки C или строковый тип STL в C ++), это фактически байтовое сравнение, поэтому сравнение UPPER ничем не отличается от lower.

Если бы вы были хитрыми и вместо этого загрузили свои строки в массивы long, вы бы получили очень быстрое сравнение всей строки, потому что она может сравнивать 4 байта за раз. Однако время загрузки может сделать его не стоящим.

Зачем вам нужно знать, что быстрее? Если вы не выполняете метрическую контрольную нагрузку сравнений, то выполнение одного цикла на пару быстрее не имеет значения для скорости общего выполнения и звучит как преждевременная оптимизация:)

6 голосов
/ 24 октября 2008

Microsoft оптимизировала ToUpperInvariant(), а не ToUpper(). Разница в том, что инвариант является более дружественным к культуре. Если вам нужно сравнивать строки без учета регистра, которые могут различаться в разных культурах, используйте Invariant, в противном случае производительность преобразования не должна иметь значения.

Я не могу сказать, быстрее ли ToUpper () или ToLower (). Я никогда не пробовал, так как у меня никогда не было ситуации, когда производительность имела такое большое значение.

4 голосов
/ 24 октября 2008

Если вы выполняете сравнение строк в C #, значительно быстрее использовать .Equals () вместо преобразования обеих строк в верхний или нижний регистр. Другим большим плюсом использования .Equals () является то, что больше памяти не выделяется для 2 новых строк верхнего / нижнего регистра.

1 голос
/ 04 июня 2010

Если все сделать правильно, должно быть небольшое, незначительное преимущество в скорости, если вы конвертируете в нижний регистр, но это, как намекнули многие, зависит от культуры и не наследуется в функции, но в конвертируемых строках строчные буквы означают несколько присваиваний памяти) - преобразование в верхний регистр происходит быстрее, если у вас есть строка с большим количеством заглавных букв.

1 голос
/ 24 октября 2008

Это действительно не должно иметь никакого значения. С символами ASCII это определенно не имеет значения - это всего лишь несколько сравнений и некоторые изменения в любом направлении. Юникод может быть немного сложнее, поскольку есть некоторые символы, которые странным образом меняют регистр, но на самом деле не должно быть никакой разницы, если в вашем тексте нет этих специальных символов.

0 голосов
/ 24 октября 2008

Зависит. Как указано выше, проста только ASCII, она идентична. В .NET читайте и используйте String.Compare , это правильно для материала i18n (языковые культуры и юникод). Если вы знаете что-либо о вероятности ввода, используйте более распространенный случай.

Помните, если вы выполняете многократное сравнение строк, длина - отличный первый дискриминатор.

0 голосов
/ 24 октября 2008

Если вы имеете дело с чистым ASCII, это не имеет значения. Это просто OR x, 32 против AND x, 224. Юникод, понятия не имею ...

...