Форум по программированию Delphi Sources

 



Вернуться   Форум по программированию Delphi Sources > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 07.03.2018, 16:02
Taras2020 Taras2020 вне форума
Прохожий
 
Регистрация: 15.01.2018
Сообщения: 29
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию Перемешивание строк / Delphi/RAD XE4

Ребята как переделать вот этот код - под чтение построчно. Что бы не загружать в память.
Код:
var
  s: TStringList;
  z, p, q: Integer;
begin
  s := TStringList.Create;
  s.LoadFromFile('C:\text.txt');
  z := 50;
  while (z > 0) do begin
    p := random(s.Count); q := random(s.Count);
    s.Exchange(p, q);
    dec(z);
  end;
  s.SaveToFile('c:\text.txt');
  s.Free;
end;

Начал переделывать вот так (но вот в регуляровкой рандом не дружу):
Код:
var
    z, p, q: Integer;
    ft, ft2: TextFile;
    s:string;
 
begin
  if OpenDialog1.Execute then begin
  AssignFile(ft, OpenDialog1.FileName);
  Reset(ft);
  AssignFile(ft2, ExtractFileDir(OpenDialog1.FileName)+'\rez.txt');
  Rewrite(ft2); // чтобы создался новый, если нету, или перезаписался с нуля
  Append(ft2); // чтобы можно было добавлять строки, а не перезаписывать каждый раз
 begin
while not eof(ft) do
 begin
readln(ft,s);
//////////////////////////////////////
Вот тут не знаю что дописать ?
//////////////////////////////////////
writeln(ft2,s)
 end;
closefile(ft);
closefile(ft2);
end;
end;
end;

Подскажите кто сможет ?
Ответить с цитированием
  #2  
Старый 07.03.2018, 23:49
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,014
Версия Delphi: D7E
Репутация: 1834
По умолчанию

http://www.delphisources.ru/forum/sh...ad.php?t=26859

Небольшое размышление: рандомное перемешивание может вызвать забавную ситуацию - некоторые строки могут быть "посланы" в результирующий файл несколько раз, а другие остаться даже неупомянутыми в нём, такова специфика системного "блендера", решение видится в таком варианте - предварительно собрать рандомный массив индексов строк с проверкой на дубляж/отсутствие их в нём и лишь после его формирования произвести перенос исходных строк в конечный файл посредством seek > readln > writeln простым проходом по элементам этого массива с последовательным считыванием их значений, по-другому вроде решение не наблюдается

З.Ы. Поскольку текстовый файл допускает лишь одностороннее чтение, только вперёд, вариант получился довольно медленным т.к. при переходе на нужную строчку необходимо каждый раз возвращаться в начало файла, много циклов, но к сожалению, иначе никак
Код:
var
    i, j, b: integer;
    ft, ft2: TextFile;
    s: string;
    sc: array of integer;
begin
 Randomize;
 AssignFile(ft, '1.txt');
 Reset(ft);
 i:= 0;

 // Подсчёт количества строк в файле
 while not Eof(ft) do
  begin
   Readln(ft);
   Inc(i);
  end;

 SetLength(sc, i);

 // Заполнение массива индексами строк
 for i := Low(sc) to High(sc) do sc[i]:= i;

 // Перемешивание индексов
 for i := High(sc) downto Low(sc) do
  begin
   b:= Random(i);
   j:= sc[b];
   sc[b]:= sc[i];
   sc[i]:= j;
  end;

 AssignFile(ft2, '2.txt');
 Rewrite(ft2);

 for i := Low(sc) to High(sc) do
  begin

   // Имитация seek
   Reset(ft);
   for j:= 0 to sc[i] do Readln(ft, s);
   
   Writeln(ft2, s);
  end;

 CloseFile(ft);
 CloseFile(ft2);
end;

Последний раз редактировалось Alegun, 08.03.2018 в 12:42.
Ответить с цитированием
Этот пользователь сказал Спасибо Alegun за это полезное сообщение:
Taras2020 (21.03.2018)
  #3  
Старый 08.03.2018, 21:04
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,161
Версия Delphi: 7, XE3, 10.2
Репутация: 49086
По умолчанию

Ну, если исходные файлы большие, то можно сделать алгоритм, который будет читать/писать блоками в несколько итераций.
Примерно так:
1. Считаем солько строк всего в файле. Пусть получили N.
2. Создаем массив длинной N.
3. В цикле от 1 до N генерируем случайную позицию для i-ой строки и помещаем ее в массив. Если место уже занято, то сдвигаем по циклу пока не найдем свободное место.
4. Берем K первых элементов массива, проходимся по файлу и собираем нужные строки, пишем их в выходной файл.
5. Повторяем 4 пока не будут записаны все блоки.
6. Profit...
Получается, что для файла длинной N строк и размера блока K строк у нас будет N%K+2 проходов по файлу.
Т.е. для примера N=1005, K=20 получаем 52 прохода.
Ответить с цитированием
  #4  
Старый 09.03.2018, 12:00
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,014
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Цитата:
Сообщение от lmikle
...можно сделать алгоритм, который будет читать/писать блоками...
Поблочная обработка, это похоже как печь блины и тесто месить для каждого блина прям на сковородке - один нормально выйдет, а другой возможно и комом, прелести местного замеса :-) Вижу только одно улучшение - можно проверить, какой был индекс предыдущим, допустим, считывалась строка 7, а следующая должна быть напр. 10-я, 7 < 10, тогда можно в начало файла не возвращаться, ссэкономить итерации цикла простым расчётом 10 - 8 = 2, две всего оставить, восемь это из-за того, что после считывания readln "курсор" на другую строчку переводит
Ответить с цитированием
  #5  
Старый 10.03.2018, 01:23
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 7,161
Версия Delphi: 7, XE3, 10.2
Репутация: 49086
По умолчанию

Не совсем так.
Тут идея уменьшения проходов по файлу. Работает, конечно, только для больших файлов. Т.е., если брать твою аналогию, то тесто ты месишь все, а вот в половник наливаешь почуть-чуть из разных мест для одного блина.
Кстати, есть еще вариант. Т.к. кол-во строк все-равно надо узнавать, то при первом проходе можно просто построить карту файла и дальше открыть его как бинарный и пользовать seek. Но карта тоже места займет в памяти.
Ответить с цитированием
Ответ



Delphi XE8

Embarcadero® Delphi XE8 — это самое быстрое решение для разработки программного обеспечения, ускоряющее проектирование, программирование и создание взаимодействующих приложений для Windows, Mac, iOS, Android и IoT. Создавайте готовые решения корпоративного класса, включая в него разные клиентские native-платформы, мобильные расширения, интеллектуальные устройства, облачные службы, корпоративные и встроенные базы данных.


Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 10:35.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2018

ВКонтакте   Facebook   Twitter