Перейти к содержанию
Fire Monkey от А до Я

Вопрос

На просторах интернета нашел вот такой старый модуль для нечеткого сравнения строк (в качестве результата число от 0 до 100):

unit FindCompare;

interface

//------------------------------------------------------------------------------
//Функция нечеткого сравнения строк БЕЗ УЧЕТА РЕГИСТРА
//------------------------------------------------------------------------------
//MaxMatching - максимальная длина подстроки (достаточно 3-4)
//strInputMatching - сравниваемая строка
//strInputStandart - строка-образец

// Сравнивание без учета регистра
// if IndistinctMatching(4, "поисковая строка", "оригинальная строка  - эталон") > 40 then ...

function IndistinctMatching(MaxMatching     : Integer;
                            strInputMatching: WideString;
                            strInputStandart: WideString): Integer;
function IndistinctMatching2(A,B: String): Real;

implementation

Uses SysUtils;

Type
     TRetCount = packed record
                 lngSubRows   : Word;
                 lngCountLike : Word;
                end;

//------------------------------------------------------------------------------
function Matching(StrInputA: WideString;
                  StrInputB: WideString;
                  lngLen: Integer) : TRetCount;
Var
    TempRet   : TRetCount;
    PosStrB   : Integer;
    PosStrA   : Integer;
    StrA      : WideString;
    StrB      : WideString;
    StrTempA  : WideString;
    StrTempB  : WideString;
begin
    StrA := String(StrInputA);
    StrB := String(StrInputB);

    For PosStrA:= 1 To Length(strA) - lngLen + 1 do
    begin
       StrTempA:= System.Copy(strA, PosStrA, lngLen);

       PosStrB:= 1;
       For PosStrB:= 1 To Length(strB) - lngLen + 1 do
       begin
          StrTempB:= System.Copy(strB, PosStrB, lngLen);
          If SysUtils.AnsiCompareText(StrTempA,StrTempB) = 0 Then
          begin
             Inc(TempRet.lngCountLike);
             break;
          end;
       end;

       Inc(TempRet.lngSubRows);
    end; // PosStrA

    Matching.lngCountLike:= TempRet.lngCountLike;
    Matching.lngSubRows  := TempRet.lngSubRows;
end; { function }

//------------------------------------------------------------------------------
function IndistinctMatching(MaxMatching     : Integer;
                            strInputMatching: WideString;
                            strInputStandart: WideString): Integer;
Var
    gret     : TRetCount;
    tret     : TRetCount;
    lngCurLen: Integer   ; //текущая длина подстроки
begin
    //если не передан какой-либо параметр, то выход
    If (MaxMatching = 0) Or (Length(strInputMatching) = 0) Or
       (Length(strInputStandart) = 0) Then
    begin
        IndistinctMatching:= 0;
        exit;
    end;

    gret.lngCountLike:= 0;
    gret.lngSubRows  := 0;
    // Цикл прохода по длине сравниваемой фразы
    For lngCurLen:= 1 To MaxMatching do
    begin
        //Сравниваем строку A со строкой B
        tret:= Matching(strInputMatching, strInputStandart, lngCurLen);
        gret.lngCountLike := gret.lngCountLike + tret.lngCountLike;
        gret.lngSubRows   := gret.lngSubRows + tret.lngSubRows;
        //Сравниваем строку B со строкой A
        tret:= Matching(strInputStandart, strInputMatching, lngCurLen);
        gret.lngCountLike := gret.lngCountLike + tret.lngCountLike;
        gret.lngSubRows   := gret.lngSubRows + tret.lngSubRows;
    end;

    If gret.lngSubRows = 0 Then
    begin
        IndistinctMatching:= 0;
        exit;
    end;

    IndistinctMatching:= Trunc((gret.lngCountLike / gret.lngSubRows) * 100);
end;

end.

В Delphi 7 отлично работает (также заработало в VCL Berlina после небольших изменений связанных с AnsiString). 

А вот чтобы заработало в Firemonkey (из-за отсутствия AnsiString) мне пришлось добавлять System.ByteStrings.dcu взятую отсюда. Так вот при запуске программы на Android я получаю более менее похожие на правду результаты, но они отличаются от тех что получаются в Delphi7. Число 100 не получается, даже если указать две одинаковые фразы (выдает около 75).

А если запускать программу под Windows, то в результате получаются самые разные рандомные числа. 

Что мешает функции нормально работать?

Изменено пользователем Rusland
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

в Berlin FMX нет AnsiString? да как так то, не может быть, в Seattle же есть...

со строками есть момент такой, сразу код, так понятней:

host = url;
int pos = host.AnsiPos( "://" );
#ifdef WIN32
  if ( pos ) host.Delete( 1, pos + 2 );
#endif
#ifdef __ANDROID__
  if ( pos ) host.Delete( 0, pos + 2 );
#endif

в общем начало строки с 1 либо с 0

Ссылка на комментарий
  • 0
44 минуты назад, krapotkin сказал:

в АНДРОИДЕ нет AnsiString

и не должно быть

Действительно, AnsiString тут и не нужен.

AnsiCompareText нужно заменить на CompareText

Изменено пользователем Rusland
Ссылка на комментарий
  • 0
56 минут назад, krapotkin сказал:

в АНДРОИДЕ нет AnsiString

и не должно быть

XE10, CBuilder, android, работаю с AnsiString, String и std::string - по ситуации, может в Delphi нет, а Андроид то тут причем?

Ссылка на комментарий
  • 0
  • Модераторы
15 минут назад, Камышев Александр сказал:

XE10, CBuilder, android, работаю с AnsiString, String и std::string - по ситуации, может в Delphi нет, а Андроид то тут причем?

http://docwiki.embarcadero.com/Libraries/Seattle/en/System.AnsiString

Note: AnsiString is used by the Delphi desktop compilers, but is not supported by the Delphi mobile compilers.

Изменено пользователем ZuBy
Ссылка на комментарий
  • 0

то что Delphi mobile compilers не работают с AnsiString - это проблема пользователей Delphi mobile compilers и минус Delphi, никак не Андроид. 

AnsiString - удобный инструмент для работы в CBuilder с ASCI и cp1251 в частности, к примеру заголовки http пакета по стандарту ASCI.

Ссылка на комментарий
  • 0
4 часа назад, Дмитрий Ш. сказал:

Кто сказал что не работает с AnsiString?

Работа гуру Delphi Andreas Hausladen http://andy.jgknet.de/blog/2016/05/system-bytestrings-for-10-1-berlin/

В первом сообщении я давал ссылку на этот метод.

Ссылка на комментарий
  • 0

Для сравнения 2-х строк хорошо подходит алгоритм Расстояние Левенштейна.  Использовал его реализацию на FMX для поиска по словарям при ошибочном вводе, используя ошибку = 2. Про производительность и пример реализации можно посмотреть тут.

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...