powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Нужен CompareText() с позицией первого отличного символа.
10 сообщений из 10, страница 1 из 1
Нужен CompareText() с позицией первого отличного символа.
    #39793739
Фотография Flying-home
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то гуглил-гуглил, так так ничего и не нашел.

Нужно быстро сравнить две строки non-case-sensitive, в результате получить позицию первого символа, который различен в исходных строках. Длину строки учитывать при сравнении не надо. Боюсь, что если буду писать сам, получится криво и медленно.

Можно сузить задачу: для списка файлов найти максимальный общий каталог. Быстро.

Сам подумал про
Код: pascal
1.
2.
3.
4.
5.
{ AnsiStrLIComp compares S1 to S2, without case-sensitivity, up to a maximum
  length of MaxLen bytes. The compare operation is controlled by the
  current user locale. The return value is the same as for CompareStr. }

function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer;


Но поиски этого MaxLen займут немало времени.

А вот тут
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
(* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The implementation of function CompareText is subject to the
 * Mozilla Public License Version 1.1 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Fastcode
 *
 * The Initial Developer of the Original Code is
 * Fastcode
 *
 * Portions created by the Initial Developer are Copyright (C) 2002-2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): John O'Harrow
 *
 * ***** END LICENSE BLOCK ***** *)
function CompareText(const S1, S2: string): Integer;
asm
        TEST   EAX, EAX
        JNZ    @@CheckS2
        TEST   EDX, EDX
        JZ     @@Ret
        MOV    EAX, [EDX-4]
        NEG    EAX
@@Ret:
        RET
@@CheckS2:
        TEST   EDX, EDX
        JNZ    @@Compare
        MOV    EAX, [EAX-4]
        RET
@@Compare:
        PUSH   EBX
        PUSH   EBP
        PUSH   ESI
        MOV    EBP, [EAX-4]     // length(S1)
        MOV    EBX, [EDX-4]     // length(S2)
        SUB    EBP, EBX         // Result if All Compared Characters Match
        SBB    ECX, ECX
        AND    ECX, EBP
        ADD    ECX, EBX         // min(length(S1),length(S2)) = Compare Length
        LEA    ESI, [EAX+ECX]   // Last Compare Position in S1
        ADD    EDX, ECX         // Last Compare Position in S2
        NEG    ECX
        JZ     @@SetResult      // Exit if Smallest Length = 0
@@Loop:                         // Load Next 2 Chars from S1 and S2
                                // May Include Null Terminator}
        MOVZX  EAX, WORD PTR [ESI+ECX]
        MOVZX  EBX, WORD PTR [EDX+ECX]
        CMP    EAX, EBX
        JE     @@Next           // Next 2 Chars Match
        CMP    AL, BL
        JE     @@SecondPair     // First Char Matches
        MOV    AH, 0
        MOV    BH, 0
        CMP    AL, 'a'
        JL     @@UC1
        CMP    AL, 'z'
        JG     @@UC1
        SUB    EAX, 'a'-'A'
@@UC1:
        CMP    BL, 'a'
        JL     @@UC2
        CMP    BL, 'z'
        JG     @@UC2
        SUB    EBX, 'a'-'A'
@@UC2:
        SUB    EAX, EBX         // Compare Both Uppercase Chars
        JNE    @@Done           // Exit with Result in EAX if Not Equal
        MOVZX  EAX, WORD PTR [ESI+ECX] // Reload Same 2 Chars from S1
        MOVZX  EBX, WORD PTR [EDX+ECX] // Reload Same 2 Chars from S2
        CMP    AH, BH
        JE     @@Next           // Second Char Matches
@@SecondPair:
        SHR    EAX, 8
        SHR    EBX, 8
        CMP    AL, 'a'
        JL     @@UC3
        CMP    AL, 'z'
        JG     @@UC3
        SUB    EAX, 'a'-'A'
@@UC3:
        CMP    BL, 'a'
        JL     @@UC4
        CMP    BL, 'z'
        JG     @@UC4
        SUB    EBX, 'a'-'A'
@@UC4:
        SUB    EAX, EBX         // Compare Both Uppercase Chars
        JNE    @@Done           // Exit with Result in EAX if Not Equal
@@Next:
        ADD    ECX, 2
        JL     @@Loop           // Loop until All required Chars Compared
@@SetResult:
        MOV    EAX, EBP         // All Matched, Set Result from Lengths
@@Done:
        POP    ESI
        POP    EBP
        POP    EBX
end;


Нужное мне число наверняка есть, но как его достать, не знаю.
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793750
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flying-home,

можно тупо сравнивать строки посимвольно, приводя все символы к верхнему или нижнему регистру (ToLower или ToUpper) до первого отличия. Преобразование регистра конечно замедлит выполнение, а так я думаю, будет достаточно быстрый вариант.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function FirstDifferent(const S1, S2: string): integer;
var i, Len: integer;
begin
  Result := 0;
  Len := Min(Length(S1), Length(S2));
  for i := 1 to Len do
  if ToLower(S1[i]) <> ToLower(S2[i]) then
  begin
    Result := i;
    Break;
  end;
end;


Возвратит позицию или 0, если короткая строка совпадает с аналогичным отрезком более длинной строки.
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793811
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flying-homeдля списка файлов найти максимальный общий каталог.
имхо: создать список путей (удалив имена файлов, но оставив слэши в конце), элементы привести к одному регистру, отсортировать по алфавиту.
Потом берем первый элемент. Это наш "бегунок".
Проверить, содержит ли последний элемент* этот бегунок. Если да - это искомое, на выход
Если нет - получить родительский каталог бегунка и на повтор предыдущей строчки

* разумеется, проверка должна включать слэш в конце, чтобы не сработать на c:/foo и c:/foobar

В итоге из затрат только сортировка и от силы 30-40 сравнений сверху (сколько там может быть вложенность, если специально не зарывать a\b\c\d...)
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793822
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Проверить, содержит ли последний элемент* этот бегунок. Если да - это искомое, на выход
Почему именно последний - все элементы должны содержать общую часть, соответственно с точностью до неё все строки начинаются одинаково. Если последний элемент не содержит бегунок, значит, этот путь явно не м.б. общим
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793877
Фотография Flying-home
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По сортировке вопрос. Я просто не совсем ясно представляю себе, как работают StringList'ы.
Мне надо первоначальный список оставить неизменным. Если я создам рабочий StringList и сделаю его строкам Assign строк первого листа, память под строки выделяться не будет. А если я в рабочем списке сделаю Sorted := true, под его строки выделится память? Хотелось бы этого избежать.
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793879
Фотография Flying-home
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2Василий 2Проверить, содержит ли последний элемент* этот бегунок. Если да - это искомое, на выход
Почему именно последний - все элементы должны содержать общую часть, соответственно с точностью до неё все строки начинаются одинаково. Если последний элемент не содержит бегунок, значит, этот путь явно не м.б. общим
Да, действительно изящно.
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793885
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flying-homeПо сортировке вопрос. Я просто не совсем ясно представляю себе, как работают StringList'ы.
Мне надо первоначальный список оставить неизменным. Если я создам рабочий StringList и сделаю его строкам Assign строк первого листа, память под строки выделяться не будет. А если я в рабочем списке сделаю Sorted := true, под его строки выделится память? Хотелось бы этого избежать.
Нет, сортировка затронет только массив указателей на строки.
Я так подумал, даже не нужно удалять имена файлов и приводить к общему регистру (разве что пути получены из разных источников). Просто Assign, Sort и дальше по схеме. Но если есть возможность путей с разным регистром - придется либо приводить к общему, либо сортировать без учета. Но это дольше
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793894
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flying-homeЯ просто не совсем ясно представляю себе, как работают StringList'ы.

они работают медленно

нужна скорость и разумное использование памяти - используй TList<string>

правда там нет все дополнительных фишект стринг-листа, типа парсинга строк Key=Value, но нужни ли они тебе?
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39793922
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Flying-homeполучить позицию первого символа, который различен в исходных строках.

а если одна строка уже кончилась, а вторая ещё нет (но пока шли обе - разницы не было), что должно получиться?
...
Рейтинг: 0 / 0
Нужен CompareText() с позицией первого отличного символа.
    #39794773
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ariochони работают медленно

нужна скорость и разумное использование памяти - используй TList<string>

Обоснуешь? Ибо сильно сомневаюсь в этом. Если не трогать name-value и text, то никакой разницы с TList быть не должно
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Нужен CompareText() с позицией первого отличного символа.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]