![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
поиск слова в тексте и удаление его !!! [D7, WinXP]
Николай,гер © (2005-06-12 01:23:00)Доброго времени суток мне нужна программа которая бы удаляла слова
в фаиле , которые присутсвуют там неколько раз. Я тут попытался сам такое написать но оно, как вы уже догодалисьс не работает. Может подскажет кто где здесь ошибка ?
код :
procedure TForm1.BitBtn1Click(Sender: TObject);
var
text,Stext ,aus : String;
Mystart, Myend: integer;
Found : integer;
gk :TSearchTypes;
textlenge ,i,t :integer;
begin
text:=Richedit1.Text;
aus:='';
textlenge:= length(text);
for i:=0 to textlenge do
begin
t:=0;
repeat
t:=t+1;
until (' '= Copy(text,t,1));
stext:= Copy (text, 0 ,t);
aus:=aus+stext+ ' ';
text := Copy (text,length(stext),textlenge );
Richedit1.Text:=text;
MyStart:=0;
MyEnd := Length(Richedit1.text);
for mystart:=0 to myend do
begin
Found :=Richedit1.FindText(Stext,MyStart,Myend,gk);
if (Found <>-1 ) then
begin
Richedit1.SelStart:=Found;
Richedit1.SelLength:=Length(Stext);
Delete(Text,Found,Length(Stext));
end;
end;
Richedit2.Text:= aus;
end;
end;
Alx2 (2005-06-12 22:48:00) [1]Вдогонку: "забивку мусором" использовал и в использовании TStringList
Alx2 (2005-06-12 22:44:00) [2]>Просто Джо © (12.06.05 22:26) [22]
Нет, я думаю дело не в скорости поиска, а в способе вставки нового элемента в TStringList.
Там для вставки используется сдвиг элементов массива.
Это занимает alpha*k времени, где k - количество элементов.
Бинарный поиск занимает beta*log(k). Итого время вставки есть
alpha*k + beta*log(k).
При пробеге по различным словам, общее количество которых есть n
получаем, что на вставку уходит beta*n*ln(n)+alpha*n*(n+1)/4+O(1/n) если бы alpha (затраты на вставку) равнялась нулю, все было-бы тип-топ. А так - сложность даже выше квадратичной.
А квадратичную сложность дает простой способ "в лоб":
Берем слово, все его дальнейшие вхождения забиваем мусором (символом, не входдящим в ValidSet).
И так для каждого слова.
Потом "выкидываем мусор" - операция по времени O(length(S)).
При проверке второй способ "в лоб" оказался действительно быстрее. (На 8Mb - в два раза)
Просто Джо (2005-06-12 22:26:00) [3]> [21] Alx2 © (12.06.05 22:13)
Для некоторого (иногда, значительного) устранения "тормозов" можно воспользоваться THashedStringList - там поиск строк реализован гораздо быстрее (через хэщ-таблицы, вероятно). Хотя, придется пожертвовать дополнительной памятью.
Alx2 (2005-06-12 22:13:00) [4]Прикола ради попытал свой код Alx2 © (12.06.05 11:41) на полуторамегабайтном файле. Получил EOutOfMemory :-)
Пришлось вместо наращивания Result сделать выкидывание из него. Иначе страшно фрагментируется куча.
Еще есть подозрения, что TStringList придает тормоза вместо ожидаемого ускорения.
Anatoly Podgoretsky (2005-06-12 21:32:00) [5]SL.CommaText:=text; или решение с DelimitedText, но для разделеных пробелом и первого хватает.
Николай_герм (2005-06-12 21:22:00) [6]а кто против ?
имеется ввиду : SL.CommaText:=text;
непремменно попробую.:)
(2005-06-12 19:21:00) [7]Удалено модератором
Примечание: Смени ник. Запятая в нике недопустима!
Anatoly Podgoretsky (2005-06-12 15:51:00) [8]Ну ты и гад, ведь ключат же в штатные телепаторы.
Alx2 (2005-06-12 15:24:00) [9]>Anatoly Podgoretsky © (12.06.05 14:21)
Снимаю шляпу.
Я так мысли читать не умею :)
Anatoly Podgoretsky (2005-06-12 14:21:00) [10]Не требуются таких сложных преобразований, для разбивки на слова (то есть чтобы записать в столбик) пользуемся встроеными срествами того же TSrilngList как CommaText, для удаления дублей Sorted и dupIgnore. Никаких других компонент не требуется. Поработай в этом направлении.
Николай,гер (2005-06-12 14:18:00) [11]ПАсибо всем я её решил и особое спасибо Anatoly Podgoretsky
вот моё решине кому интерестно
//для того что бы можно было использовать TStringList нужно сначала текст ненмого обработать
procedure TForm1.ffnen1Click(Sender: TObject);
var
text,teiltex: string;
i:integer;
begin
Richedit1.Lines.LoadFromFile('mail.rtf');
text:=Richedit1.Text;
teiltex:='';
for i:=0 to length(text) do
begin
if (' '= text[i])then
begin
listbox1.Items.Add(teiltex);// Приходится использовать listbox1 для того что бы записать текст в столбик а удаление находится в следующей процедуре
Teiltex:='';
end
else Teiltex:=teiltex+ text[i]
end ;
Richedit1.Lines:=ListBox1.Items;
end;
//Следующая процедура которая находит дупликаты и убивает их
procedure TForm1.BitBtn1Click(Sender: TObject);
var
SL : TStringList;
text: string;
td:TDuplicates;
begin
text:=Richedit1.Text;
SL:=TStringList.Create;
SL.Sorted:=true;
td:=dupIgnore; // Это значеине игнорирует все двойник в файле
SL.Duplicates:=td;
SL.Text:=text;
Richedit2.Text:=SL.Text;
end;
Николай,гер (2005-06-12 13:43:00) [12]
var
SL : TStringList;
text: string;
td:TDuplicates;
begin
td:=dupIgnore;
SL.Duplicates:=td;
это так выглидит ?
если да то оно не работает :(
Alx2 (2005-06-12 13:35:00) [13]>Anatoly Podgoretsky © (12.06.05 13:14) [11]
Получится только в частных случаях.
Anatoly Podgoretsky (2005-06-12 13:14:00) [14]Текст загоняется в StringList - Sorted, Ignore Dups
Николай,гер (2005-06-12 13:02:00) [15]Спасибо это то что надо , с этим буду дальше ковырятся :)
Alx2 (2005-06-12 11:41:00) [16]Например:
function WordsFilter(const S: string): string;
const // Множество символов, непрерывная цепочка которых есть слово.
ValidSet = ['a'..'z', 'A'..'Z', 'а'..'я', 'А'..'Я', '0'..'9'];
var SLen: Integer;
function GetWord(var Idx: Integer; var Dust: string): string;
var Start: Integer;
begin
Result := '';
Start := Idx;
// Пропускаем мусор
while (Idx <= SLen) and not (S[Idx] in ValidSet) do Inc(Idx);
// Мусор пригодится, так как не сказано, что его надо удалять
Dust := Dust + Copy(S, Start, Idx - Start);
Start := Idx;
// Формируем слово
while (Idx <= SLen) and (S[Idx] in ValidSet) do Inc(Idx);
Result := Copy(S, Start, Idx - Start);
end;
var
Idx: Integer;
Word, Dust: string;
begin
Result := '';
with TStringList.Create do
try
Duplicates := dupIgnore;
CaseSensitive := True;
Sorted := true;
SLen := Length(S);
Idx := 1;
Dust := '';
while Idx <= sLen do
begin
Word := GetWord(Idx, Dust);
if IndexOf(Word) < 0 then // Если слово не "запрещенное"
begin
Add(Word); // То делаем его запрещенным и дописываем в результат.
Result := Result + Dust + Word;
Dust := ''; // Мусор сбрасываем, так как он уже попал в результат.
end;
end;
finally
Free;
end;
end;
begin
// Пример использования
ShowMessage(WordsFilter('test test1, test1, alpha, beta beta, gamma'));
end;
Alx2 (2005-06-12 11:29:00) [17]>Николай,гер (12.06.05 11:23) [7]
>Да нет там запрещённых слов, в том то и дело .
Запрещенными я назвал слова, чьи повторы имеются.
На первом шаге их нет, конечно. А потом появляются.
Если слово лежит в списке запрещенных, значит оно встречалось ранее и вновь встретится не должно.
Николай,гер (2005-06-12 11:23:00) [18]Да нет там запрещённых слов, в том то и дело . Программа должна сама сравнивать все слова которые там находятся и выкидвать их повторы если таковые имеются.
но всё равно спасибо за совет
Да а как конкретно это зделать ?
Alx2 (2005-06-12 11:14:00) [19]Заводим отсортированный список "запрещенных" слов. Читаем строчку по словам. Ели очередное слово в списке - читем дальше. Иначе, добавляем слово в список и в результат.
Николай,гер (2005-06-12 10:57:00) [20]нет не запалдо , просто я английским не владею