Фильтр по шаблону
Модератор: Модераторы
Фильтр по шаблону
Как реализовать фильтр по шаблону?
Например мне нужно отфильтровать всё подобное этому:
9678.596.45.1297
XXXX.XXX.XX.XXXX
X - цифра
Например мне нужно отфильтровать всё подобное этому:
9678.596.45.1297
XXXX.XXX.XX.XXXX
X - цифра
- AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
из массива строк выбрать только строки , состоящие из чисел , разделенных точками ? ) 
А пример можно?
- AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
вот что-то получилось ) Функция ищет в строке точку или число. Если вместо точки или числа что-то другое - вернет false.
Для точного разбора шаблона , мне кажется , целесообразно написать класс , который будет заниматься абсолютным сравнением шаблона с входящей строкой и т.д. )) Может и есть возможность решить такую задачу одной функцией , но я запуталась у меня не получилось ))) Слишком много условий для моего маленького ума )
Алгоритм примерно такой :
1.Сравнить количество символов в строке и шаблоне .
Если они равны:
2. Сравнить позиции точек в шаблоне с позициями точек в строке
Если они равны :
3. Перебирая строку по символам проверить - нет ли в строке других символов , кроме чисел и точек .
Для точного разбора шаблона , мне кажется , целесообразно написать класс , который будет заниматься абсолютным сравнением шаблона с входящей строкой и т.д. )) Может и есть возможность решить такую задачу одной функцией , но я запуталась у меня не получилось ))) Слишком много условий для моего маленького ума )
Алгоритм примерно такой :
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;
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
AlphaBlend, в подобных случаях использование цикла for не очень корректно. Проще выход по условию. Я бы проверял строки по всем условиям, а не подходящую обнулял бы.
- AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
Лекс Айринспасибо , буду знать )
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
в смысле, в возвращенном результате, а не в параметрах.
- AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
Лекс Айрин можно после flag:=false; добавить break; Тогда цикл завершится сразу , как только найдется символ , который НЕ число и НЕ точка , и функция сразу вернет false ? ) Это же будет правильно ?
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
AlphaBlend, вообще-то, именно подобных конструкций стоит избегать... как правило, частое их использование говорит о не умении управлять условиями и подбором подходящего в данный момент цикла. Да и потом, если потом потребуется что-то где-то обнулить или выбрать альтернативную ветку выполнения программы и придется убирать.
вот, например, работа сложной проверки -- выхлоп четыре варианта результатов.
ЗЫ: проверки показали, что фактически операторы (функции) прерывания цикла оптимизатором убираются, а условия ветвления изменяются так чтобы необходимость в них не возникла.
Добавлено спустя 8 минут 58 секунд:
ну и, до кучи, объявление TTag
вот, например, работа сложной проверки -- выхлоп четыре варианта результатов.
Код: Выделить всё
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; - AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
Лекс Айрин у каков
а какой алгоритм можете посоветовать в случае задачи этого поста ?
- alexs
- долгожитель
- Сообщения: 4066
- Зарегистрирован: 15.05.2005 23:17:07
- Откуда: г.Ставрополь
- Контактная информация:
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;
Лекс Айрин
Всё зависит от условий. Но декомпозиция очень способствует облечению чтения кода. Ваш пример узкозаточен. И тоже допускает оптимизацию.
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
alexs писал(а):Ваш пример узкозаточен. И тоже допускает оптимизацию.
Безусловно. Я лишь привел пример. Насчет оптимизации я бы послушал внимательно...
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
- AlphaBlend
- постоялец
- Сообщения: 207
- Зарегистрирован: 22.05.2016 09:13:10
alexs , Лекс Айрин
круто ) когда прочитаешь готовый код - все так просто кажется ))) Видимо , я не те учебники читаю ))
Добавлено спустя 7 минут 30 секунд:
resident мне кажется , что break нужен )) Представьте , когда проверяемых строк будет десять тысяч , а символов в строке - 255 ? ) С любой скоростью будет много-много лишних циклов , занимающих впустую процессорное время, которое можно будет потратить на какую-нибудь полезность ) Конечно , при таких объемах необходимо использовать потоки , но все же ) Надо учитывать разную аппаратную конфигурацию ) Может программа будет где-нибудь на мало-мальски работающем компьютере , который еле-еле удовлетворяет требованиям XP ?)
Добавлено спустя 7 минут 30 секунд:
resident мне кажется , что break нужен )) Представьте , когда проверяемых строк будет десять тысяч , а символов в строке - 255 ? ) С любой скоростью будет много-много лишних циклов , занимающих впустую процессорное время, которое можно будет потратить на какую-нибудь полезность ) Конечно , при таких объемах необходимо использовать потоки , но все же ) Надо учитывать разную аппаратную конфигурацию ) Может программа будет где-нибудь на мало-мальски работающем компьютере , который еле-еле удовлетворяет требованиям XP ?)
Спасибо всем, буду переваривать! 
