|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Перемешивание строк / 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
|
||||
|
||||
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
|
|||
|
|||
Ну, если исходные файлы большие, то можно сделать алгоритм, который будет читать/писать блоками в несколько итераций.
Примерно так: 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
|
||||
|
||||
Цитата:
Я не понял Вашего вопроса, но всё же Вам на него отвечу! |
#5
|
|||
|
|||
Не совсем так.
Тут идея уменьшения проходов по файлу. Работает, конечно, только для больших файлов. Т.е., если брать твою аналогию, то тесто ты месишь все, а вот в половник наливаешь почуть-чуть из разных мест для одного блина. Кстати, есть еще вариант. Т.к. кол-во строк все-равно надо узнавать, то при первом проходе можно просто построить карту файла и дальше открыть его как бинарный и пользовать seek. Но карта тоже места займет в памяти. |