Поиск одинаковых строк в текстовом файле
Имеется база вида (Где есть повторяющиеся строки):
+Результат
+Ошибка
+Результат
+Результат
+Результат
+Ошибка
......
Нужно посчитать все повторяющиеся строки что расположены в текстовом файле и вывести отчет в Memo1. Результат должен получится в Memo1 такой:
+Результат - 4 раза
+Ошибка - 2 раза
То есть посчитать все одинаковые строки что есть в текстовом файле и статистику вывести в Memo1.
Предоставленный код работает быстро но вот при размерах файла в 600 мегабайт выдает сообщение о нехватке памяти. Ну это и понятно потому как мы все грузим в память.
procedure TForm1.Button1Click(Sender: TObject);
var
TS: TStringList;
s, OneWord: string;
i, Cnt: integer;
begin
TS := TStringList.Create;
TS.Delimiter := '+';
TS.LoadFromFile('baza.txt');
s := TS.Text;
TS.DelimitedText := s;
if TS.Count = 0 then
begin
ShowMessage('Вообще ни одного слова нет!');
Exit;
end;
TS.Sort;
Memo1.Lines.Clear; // подготовим место для формирования отчёта
// собственно подсчёт
OneWord := TS.Strings[0];
Cnt := 1;
for i := 1 to TS.Count - 1 do
if AnsiUpperCase(TS.Strings[i]) = AnsiUpperCase(OneWord) then
inc(Cnt)
else
begin
Memo1.Lines.Append(OneWord + '+' + InttoStr(Cnt));
OneWord := TS.Strings[i];
Cnt := 1;
end;
// для последнего слова в списке вывод результата
Memo1.Lines.Append(OneWord + '+' + InttoStr(Cnt));
FreeAndNil(TS); // освободим память
end;
Пробовала оформить код через AssignFile - чтение построчно но у меня тут ошибки. Помогите исправить ?
var
TS: TStringList;
s,st: string;
i, Cnt: integer;
f1: TextFile;
begin
Memo1.Lines.Clear; // подготовим место для формирования отчёта
// Открываем диалог выбора файла
if not OpenDialog1.Execute then
exit
else
AssignFile(f1, OpenDialog1.FileName);
reset(f1);
TS := TStringList.Create;
TS.Delimiter := '+';
s := TS.Text;
TS.DelimitedText := s;
TS.Sort;
if TS.Count = 0 then
begin
ShowMessage('Вообще ни одного слова нет!');
exit;
end;
While not EOF(f1) do
begin
// Что бы программа не подвисала
Application.ProcessMessages();
readln(f1, st);
TS.Add(st);
// собственно подсчёт
st := TS.Strings[0];
Cnt := 1;
for i := 1 to TS.Count - 1 do
if AnsiUpperCase(TS.Strings[i]) = AnsiUpperCase(st) then
inc(Cnt)
else
begin
Memo1.Lines.Append(st + '-' + InttoStr(Cnt));
st := TS.Strings[i];
Cnt := 1;
end;
// для последнего слова в списке вывод результата
Memo1.Lines.Append(st + '-' + InttoStr(Cnt));
FreeAndNil(TS); // освободим память
end;
TS.Free;
CloseFile(f1);
end;
Ответы (1 шт):
Автор решения: MBo
→ Ссылка
var
Dict: TDictionary<string, integer>;
f: TextFile;
s:string;
cnt: Integer;
A: TArray<TPair<string, integer>>;
p: TPair<string, integer>;
begin
Dict := TDictionary<string, integer>.Create;
AssignFile(f, 'e:\s.txt');
Reset(f);
while not EOF(f) do begin
Readln(f, s);
Dict.TryGetValue(s, cnt);
Dict.AddOrSetValue(s, cnt + 1);
end;
CloseFile(f);
// for s in dict.Keys do
// Memo1.Lines.Add(s + ': ' +Dict.Items[s].ToString);
A:= Dict.ToArray;
TArray.Sort<TPair<string, Integer>>(A,
TComparer<TPair<string, Integer>>.Construct(
function (const L, R: TPair<string, Integer>): Integer
begin
Result := -CompareStr(L.Key, R.Key);
end)
);
for p in A do
Memo1.Lines.Add(p.Key + ': ' + p.Value.ToString);
Dict.Free;