сравнение строк
От: Аноним  
Дата: 07.12.07 16:18
Оценка: 74 (2)
У меня есть следующий тестовый код:
            string s1, s2;
            int res;
            s1 = "CSK."; s2 = "CSK-";
            res = CompareTo(s1, s2);
            Console.WriteLine(res);

            s1 = "CSK.S"; s2 = "CSK-V";
            res = CompareTo(s1, s2);
            Console.WriteLine(res);

Результат
1
-1

Я ожидал не такое поведение. Получается, длина строки влияет на результат сравнения или вес последних символов больше веса первых символов?
Вопрос 1: Как мне добиться, чтобы на выходе было 1, 1 ну или -1, -1?
Вопрос 2: Почему я получаю такой результат?
Re: сравнение строк
От: Mab Россия http://shade.msu.ru/~mab
Дата: 07.12.07 16:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я ожидал не такое поведение.

А зря. В лексикографическом порядке префикс строки всегда предшествует ей самой.
Re[2]: сравнение строк
От: WolfHound  
Дата: 07.12.07 16:50
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>А зря. В лексикографическом порядке префикс строки всегда предшествует ей самой.

Тут прикол в другом.
Смотри:
        static void Main(string[] args)
        {
            string[] strings = new string[] { "CSK.", "CSK-", "CSK.S", "CSK-V" };
            Array.Sort<string>(strings);
            foreach (string s in strings)
                Console.WriteLine(s);
        }

CSK-
CSK.
CSK.S
CSK-V

Аналогичный код на С++
    std::vector<std::string> strings;
    strings.push_back("CSK.");
    strings.push_back("CSK-");
    strings.push_back("CSK.S");
    strings.push_back("CSK-V");
    std::sort(strings.begin(), strings.end());
    for (size_t i = 0; i < strings.size(); ++i)
        std::cout << strings[i] << std::endl;

CSK-
CSK-V
CSK.
CSK.S


ИМХО Баг в фреймворке.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: сравнение строк
От: WolfHound  
Дата: 07.12.07 17:28
Оценка:
Здравствуйте, WolfHound, Вы писали:

Линуховый sort согласен с C#
CSK-
CSK.
CSK.S
CSK-V

Это уже становится интересно
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: сравнение строк
От: Cyberax Марс  
Дата: 07.12.07 17:57
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Линуховый sort согласен с C#

WH>
WH>CSK-
WH>CSK.
WH>CSK.S
WH>CSK-V
WH>

WH>Это уже становится интересно

В Java — не согласен:
Str: CSK-
Str: CSK-V
Str: CSK.
Str: CSK.S


Похоже, что в Линуксовом сорте и C# сделана оптимизация — сначала сравниваются длины строк. В Java и С++ же используется полное лексиографическое сравнение.

В общем, просто разные подходы.
Sapienti sat!
Re[5]: сравнение строк
От: WolfHound  
Дата: 07.12.07 18:04
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Похоже, что в Линуксовом сорте и C# сделана оптимизация — сначала сравниваются длины строк. В Java и С++ же используется полное лексиографическое сравнение.

C>В общем, просто разные подходы.
Тут нужно еще учитывать что "-" < "."
Таким образом должно быть как минимум так
CSK-
CSK.
CSK-V
CSK.S

А не так
CSK-
CSK.
CSK.S
CSK-V
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: сравнение строк
От: ie Россия http://ziez.blogspot.com/
Дата: 07.12.07 18:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос 1: Как мне добиться, чтобы на выходе было 1, 1 ну или -1, -1?


string.CompareOrdinals?
Превратим окружающую нас среду в воскресенье.
Re[6]: сравнение строк
От: Cyberax Марс  
Дата: 07.12.07 18:44
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>А не так

WH>
WH>CSK-
WH>CSK.
WH>CSK.S
WH>CSK-V
WH>

Может они с концов начинают сравнивать (есть такая оптимизация)?
Sapienti sat!
Re[6]: сравнение строк
От: Cyberax Марс  
Дата: 07.12.07 18:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>
WH>CSK-
WH>CSK.
WH>CSK.S
WH>CSK-V
WH>

Еще вариант — кастят к int'ам пары символов и сравнивают арифметически. Как раз так и должно получаться.
Sapienti sat!
Re[7]: сравнение строк
От: Mab Россия http://shade.msu.ru/~mab
Дата: 07.12.07 18:56
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Может они с концов начинают сравнивать (есть такая оптимизация)?

Может быть все что угодно, я не смог понять, где именно эта особенность заложена в методе NativeCompareInfo::CompareString.

И потом, о какой оптимизации речь? При лексикографическом сравнении нужно начинать с начала просто по определению. И еще, для строк a, ax, b, bx такого эффекта нет. Так что не знаю, в чем дело.
Re[8]: сравнение строк
От: Cyberax Марс  
Дата: 07.12.07 19:02
Оценка:
Здравствуйте, Mab, Вы писали:

C>>Может они с концов начинают сравнивать (есть такая оптимизация)?

Mab>Может быть все что угодно, я не смог понять, где именно эта особенность заложена в методе NativeCompareInfo::CompareString.
Mab>И потом, о какой оптимизации речь? При лексикографическом сравнении нужно начинать с начала просто по определению. И еще, для строк a, ax, b, bx такого эффекта нет. Так что не знаю, в чем дело.
Почитал доку на MSDN. Тогда еще возможен вариант с глючащей CultureInfo.
Sapienti sat!
Re: сравнение строк
От: alexsoff Россия  
Дата: 09.12.07 18:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я ожидал не такое поведение. Получается, длина строки влияет на результат сравнения или вес последних символов больше веса первых символов?

А>Вопрос 1: Как мне добиться, чтобы на выходе было 1, 1 ну или -1, -1?
А>Вопрос 2: Почему я получаю такой результат?
Используйте

String.CompareOrdinal(string,string);

И результат будет ожидаемым
Re[2]: сравнение строк
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.12.07 04:26
Оценка: +1
Здравствуйте, alexsoff, Вы писали:
A>
A>String.CompareOrdinal(string,string);
A>

A>И результат будет ожидаемым
Это мы уже выяснили. Пока остается непонятным нежелание дотнета выполнять лексикографическую сортировку при всех остальных способах сравнения.
Честно говоря, мне это непонятно. Свойства лексикографической сортировки очень удобны; ordinal, если я правильно понял, тупо сравнивает номера Code Point, что далеко не всегда соответствует поставленной цели.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: сравнение строк
От: alexsoff Россия  
Дата: 10.12.07 11:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

Пока остается непонятным нежелание дотнета выполнять лексикографическую сортировку при всех остальных способах сравнения.
Народ хватит паниковать:
SQL Server 2005)
select 
 txt
from
(
    select 'CSK.' as txt
    union all 
    select 'CSK-'
    union all
    select 'CSK.S'
    union all
    select 'CSK-V'
) t
order by txt

Результат:

CSK-
CSK.
CSK.S
CSK-V

Это видимо правила такие сортировки со знаками препинания, а не очередной баг в майкрософт.
Сравнение строк
От: yg  
Дата: 10.12.07 13:50
Оценка: 439 (21)
#Имя: FAQ.dotnet.string.compare
>У меня есть следующий тестовый код:
            string s1, s2;
            int res;
            s1 = "CSK."; s2 = "CSK-";
            res = CompareTo(s1, s2);
            Console.WriteLine(res);

            s1 = "CSK.S"; s2 = "CSK-V";
            res = CompareTo(s1, s2);
            Console.WriteLine(res);

>Результат
1
-1

>Я ожидал не такое поведение. Получается, длина строки влияет на результат сравнения или вес последних символов больше веса первых символов?
>Вопрос 1: Как мне добиться, чтобы на выходе было 1, 1 ну или -1, -1?
>Вопрос 2: Почему я получаю такой результат?

Фишка в том, что по умолчанию при сравнении строк в .NET символы апострофа и дефиса имеют очень малые веса. Фактически они учитываются только если строки совпадают за исключением этих символов.

Вот выдержка из MSDN:

The .NET Framework uses three distinct ways of sorting: word sort, string sort, and ordinal sort. Word sort performs a culture-sensitive comparison of strings. Certain nonalphanumeric characters might have special weights assigned to them; for example, the hyphen ("-") might have a very small weight assigned to it so that "coop" and "co-op" appear next to each other in a sorted list. String sort is similar to word sort, except that there are no special cases; therefore, all nonalphanumeric symbols come before all alphanumeric characters. Ordinal sort compares strings based on the Unicode values of each element of the string.


Изменить способ сортировки можно при помощи перечисления CompareOptions.
Чтобы включить "ordinal sort", использовать CompareOptions.Ordinal.
Чтобы включить "string sort", использовать CompareOptions.StringSort.

Меня слегка удивляет, что по умолчанию включено "word sort", а не "string sort"... Например, как уже тут говорили, SQL Server по умолчанию сортирует обычным способом. А поскольку SQL Server и .NET — это стандартная связка, то получаем красиво и со вкусом разложенные грабли.

Люди! Будьте осторожны!
Re[2]: сравнение строк
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.12.07 03:48
Оценка:
Здравствуйте, yg, Вы писали:
Обалдеть! Посыпаю голову своего невежества пеплом твоей эрудиции.
А где именно в MSDN это написано?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: сравнение строк
От: desco США http://v2matveev.blogspot.com
Дата: 11.12.07 06:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, yg, Вы писали:

S>Обалдеть! Посыпаю голову своего невежества пеплом твоей эрудиции.
S>А где именно в MSDN это написано?

String Class
Re[4]: сравнение строк
От: alex_mah Россия www.elsy.ru
Дата: 06.02.08 11:00
Оценка:
Здравствуйте, alexsoff, Вы писали:

A>Результат:

A>

A>CSK-
A>CSK.
A>CSK.S
A>CSK-V


Странно. А у меня и MS SQL Server 2000 и MS SQL Server 2005 выдали


txt   
----- 
CSK-
CSK-V
CSK.
CSK.S

(4 row(s) affected)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.