Фильтр по шаблону

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Фильтр по шаблону

Сообщение eoleg » 26.05.2016 11:25:05

Как реализовать фильтр по шаблону?
Например мне нужно отфильтровать всё подобное этому:
9678.596.45.1297
XXXX.XXX.XX.XXXX
X - цифра
eoleg
новенький
 
Сообщения: 14
Зарегистрирован: 01.04.2016 10:43:20

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 12:16:18

из массива строк выбрать только строки , состоящие из чисел , разделенных точками ? ) :roll:
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение eoleg » 26.05.2016 12:49:25

А пример можно?
eoleg
новенький
 
Сообщения: 14
Зарегистрирован: 01.04.2016 10:43:20

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 14:08:56

вот что-то получилось ) Функция ищет в строке точку или число. Если вместо точки или числа что-то другое - вернет false.
Для точного разбора шаблона , мне кажется , целесообразно написать класс , который будет заниматься абсолютным сравнением шаблона с входящей строкой и т.д. )) Может и есть возможность решить такую задачу одной функцией , но я запуталась у меня не получилось ))) Слишком много условий для моего маленького ума )
Алгоритм примерно такой :
1.Сравнить количество символов в строке и шаблоне .
Если они равны:
2. Сравнить позиции точек в шаблоне с позициями точек в строке
Если они равны :
3. Перебирая строку по символам проверить - нет ли в строке других символов , кроме чисел и точек .


Код: Выделить всё

function EmptyParseTemplate(InputStr: String):boolean;
var
  Numbers: set of '0'..'9';
  i:integer;
  flag:boolean;
begin

   flag:=true;
     Numbers:=['0'..'9'];
     for i:=1 to Length(InputStr) do
         begin
             if (not (InputStr[i] in Numbers )) and (not (InputStr[i] = '.')) then flag:=false;
         end;
   result:=flag;

end;                         
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение Лекс Айрин » 26.05.2016 14:28:18

AlphaBlend, в подобных случаях использование цикла for не очень корректно. Проще выход по условию. Я бы проверял строки по всем условиям, а не подходящую обнулял бы.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 14:29:55

Лекс Айринспасибо , буду знать )
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение Лекс Айрин » 26.05.2016 14:30:29

в смысле, в возвращенном результате, а не в параметрах.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 14:35:47

Лекс Айрин можно после flag:=false; добавить break; Тогда цикл завершится сразу , как только найдется символ , который НЕ число и НЕ точка , и функция сразу вернет false ? ) Это же будет правильно ?
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение Лекс Айрин » 26.05.2016 16:07:52

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

Код: Выделить всё
function FirstTag (var Str:String):TTag;
Var
   Start, Finish:boolean;
   StrTag:String;
Begin
     If Str='' then
      begin
        Result.Str:='';//отсев ошибочного использования
      end else
      begin
           Start:=False;  // инициализация переменных.
           Finish:=False;
           Result.Str:='';
           Result.tags:=true;
           StrTag:='';

           while Finish=false do   //
           begin
           if Str='' then
             Begin
                  Finish:=True;//выход из цикла по исчерпанию строки. условия выхода могут быть любые
                  Result.tags:=false;
             End else

             Begin
                  StrTag:=Copy(Str,1,1);
                  case  StrTag of
                    '<':
                      Begin
                      if Start=true then
                        Begin  //это второй символ '<'
                          Finish:=True; // штатный выход если это все же не тег.
                          Result.tags:=false;

                        end else  //это первый символ '<'.
                        begin   // начинаем копировать предположительно тег в строку

                            if  Result.Str='' then
                              begin
                                    Start:=True;
                                    Result.Str:=Result.Str+StrTag;
                                    Delete(Str, 1, 1);
                              end else
                            begin  // результат  -- все, что до символа '<' НЕ тег
                                   Finish:=True;
                                   result.tags:=false;

                            end;

                        end

                      end;
                    '>':
                      Begin
                           Result.Str:=Result.Str+StrTag;
                           Delete(Str, 1, 1);

                           if Start=true then
                             begin
                               Finish:=True;// штатный выход если тег

                               result.tags:=true;
                             end else
                             begin
                                Finish:=True;// штатный выход если НЕ тег
                                result.tags:=false;
                             end;

                      end;
                  else Begin
                            Result.Str:=Result.Str+StrTag; // обычный символ
                            Delete (Str, 1, 1);

                       End;
                  end;
             end;
           end;
      end;
end;

function TestTag (Str:TTag):Boolean;
Var
  TempStr:string;

Begin
    TempStr:=Copy(Str.Str,0,4);//больше 4 вряд ли потребуется

{
теги после которых строка переводится:
<bp> </h1 <h2 <h3 </p> </di </ta </tr </th </tb </li
во всех остальных случаях нет!}
    //showMessage ('function TestTag -- TempStr='+TempStr);
    case TempStr   of
      '<bp>', '</h1', '<h2', '<h3', '</p>', '</di', '</ta', '</tr', '</th', '</tb', '</li'
      :begin
        result:=true;
       end;             




ЗЫ: проверки показали, что фактически операторы (функции) прерывания цикла оптимизатором убираются, а условия ветвления изменяются так чтобы необходимость в них не возникла.

Добавлено спустя 8 минут 58 секунд:
ну и, до кучи, объявление TTag
Код: Выделить всё
Type
  OnOff=boolean;
  TTag=record
    Str:String;
   // verify:OnOff;
    tags:boolean;
  end;

Const
    ValueOn=true;
    ValueOff=False;     
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 16:29:47

Лекс Айрин у каков :shock: а какой алгоритм можете посоветовать в случае задачи этого поста ?
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение alexs » 26.05.2016 16:48:04

AlphaBlend
Ваш алгоритм нормален. Но слишком много переменных и лишние проборы по циклу.
Код: Выделить всё
function EmptyParseTemplate(InputStr: String):boolean;
var
  i:integer;
begin
   for i:=1 to Length(InputStr) do
     if not (InputStr[i] in ['.', '0'..'9']) then
       exit(False);
  Result:=true;
end;

Лекс Айрин
Всё зависит от условий. Но декомпозиция очень способствует облечению чтения кода. Ваш пример узкозаточен. И тоже допускает оптимизацию.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Фильтр по шаблону

Сообщение Лекс Айрин » 26.05.2016 17:01:36

alexs писал(а):Ваш пример узкозаточен. И тоже допускает оптимизацию.


Безусловно. Я лишь привел пример. Насчет оптимизации я бы послушал внимательно...
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Фильтр по шаблону

Сообщение resident » 26.05.2016 17:05:55

AlphaBlend писал(а):а какой алгоритм можете посоветовать в случае задачи этого поста ?

Взял ваш алгоритм. Только вместо проверки всей длины строки проверяю только 16 символов как в шаблоне.
Итого ваш алгоритм внутри еще двух циклов: 1) Внешний (i) пробегает по всем строкам файла (sList), 2) А внутри (k) по символам строки.
Получается если в любой строке, начиная с любого символа (Ch) ваш алгоритм относительно вырезанного фрагмента 16 символов даст положительную оценку, то копирую эту подстроку 16 символов в ответ (sListOut).
Код: Выделить всё
    for i := 0 to Pred(sList.Count) do
      for k := 1 to Length(sList[i]) - 15 do
        begin
          Flag := true;
          m := 0;
          while Flag and (m < 16) do
            begin
              Ch := sList[i][k + m];
              if (m = 4) or (m = 8) or (m = 11) then
                Flag := Flag and (Ch = '.') else
                Flag := Flag and (Ch in ['0'..'9']);
              Inc(m);
            end;
          if Flag then sListOut.Append(Copy(sList[i], k, 16));
        end; 

AlphaBlend писал(а):можно после flag:=false; добавить break

Я даже break не ставлю, с современным скоростями все летает. (Исправил на while, чтоб не прикапались :) ).

зы.
exe
resident
энтузиаст
 
Сообщения: 605
Зарегистрирован: 13.03.2013 16:58:51

Re: Фильтр по шаблону

Сообщение AlphaBlend » 26.05.2016 18:48:32

alexs , Лекс Айрин :mrgreen: круто ) когда прочитаешь готовый код - все так просто кажется ))) Видимо , я не те учебники читаю ))

Добавлено спустя 7 минут 30 секунд:
resident мне кажется , что break нужен )) Представьте , когда проверяемых строк будет десять тысяч , а символов в строке - 255 ? ) С любой скоростью будет много-много лишних циклов , занимающих впустую процессорное время, которое можно будет потратить на какую-нибудь полезность ) Конечно , при таких объемах необходимо использовать потоки , но все же ) Надо учитывать разную аппаратную конфигурацию ) Может программа будет где-нибудь на мало-мальски работающем компьютере , который еле-еле удовлетворяет требованиям XP ?)
Аватара пользователя
AlphaBlend
постоялец
 
Сообщения: 207
Зарегистрирован: 22.05.2016 10:13:10

Re: Фильтр по шаблону

Сообщение eoleg » 26.05.2016 19:13:17

Спасибо всем, буду переваривать! :D
eoleg
новенький
 
Сообщения: 14
Зарегистрирован: 01.04.2016 10:43:20

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 28

Рейтинг@Mail.ru
cron