[perl] извлечение подмассива из массива

Fake_queen

из десятка файла, содержащих простой список с числами, размером под 140 мегов каждый в определенном порядке должны извлекаться подмассивы чисел. таких обращений к каждому файлу будет порядка 1000. алгоритм процедуры очень простой, что то вроде этого (под рукой нет скрипта)

sub extract {
($name.list,$offset,$len)=@_;
open(fi,"$name.list.txt"); @seq = <fi>; close fi;
return splice (@seq,$offset,$len);
}

проблема в том, что такая операция ОЧЕНЬ сильно загружает операционку, на маломощном компе вообще вылетает сообщение об ошибке. как бы оптимизировать извлечение подмассивов, перегружая комп по минимуму?

Fake_queen

да, ессно, использую use strict и внутри блока процедуры перед переменными стоит my.

evgen5555

как бы оптимизировать извлечение подмассивов, перегружая комп по минимуму?
А сам как думаешь? :)

Geddi-S

read, sysread
формат файла какой?

sakura

@seq = <fi>;
Вот в этом проблема. Зачем тебе выгружать все содержимое файла в "операционку"? Читай построчно и выбирай нужные строки.

Fake_queen

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

Fake_queen

это то (не работает пробел :) ) понятно, собственно и хотел бы от этого избавится, но пока не понял как. а если построчно, то как делать splice?

Fake_queen

0.001
0.974
0.784
и т.д.
расширение txt, но это не важно

Bibi

а у тебя отрицательный $offset и $length могут использоваться при вызове? или могут ли они быть опущены?
просто если это так, то при построчном чтении файла для того же результата, что дает splice, придется немного подзаморочиться.
если нет, то проблем никаких быть не должно. вводишь счетчик строк и вперед.

Geddi-S

Понятно
поэтому на самом деле в массиве строки файла, которые по счастливой случайности являются числами
если числа одного формата (под каждое одно и то же число символов то рассчитывай параметр $offset в
seek ($fh, $offset, 0)
и читай посимвольно
думаю, идея понятна

Fake_queen

все положительное. ну видимо да, так и придется, построчно. хотелось изначально все таки со splice все сделать

pitrik2

хотелось изначально все таки со splice все сделать
хехе
как ты себе это представляешь?
если токо подсунуть ему хитрый аррэй, который заполняется по мере обращения к нему
даже если бы такое и было возможно (на скоко я знаю в перле симпл типы нельзя унаследовать) то кода у тебя было бы явно больше чем 2 строчки
на считывание строки и инкрементирование счетчика

Fake_queen

$offset в случае seek это просто номер строки?

Fake_queen

я имел ввиду тот вариант, который в первом посте, без построчного обращения к файлу

Bibi

ваще, конечно, если есть sed под рукой, то круче сделать так:

`sed -n '$start,$end\p;$end\q' $filename`

Fake_queen

да, sed это вариант, сейчас просвещаюсь по нему

pitrik2

по-любому ты 1000 раз лазаешь по 140-меговому файлу
может можно видоизменить алгоритм чтобы в эту функцию передавать сразу все интервалы и за один проход все считывать?

Fake_queen

можно будет попробовать, но изменение будет слишком долгим (другие дела торопят); пока мне больше нравится вариант с sed

Bibi

так одно другое не исключает, ведь, если я правильно понимаю, что речь идет именно о вызове этой обработки для одного файла несколько раз и если при этом эти интервалы строк пересекаются.
если не пересекаются, то экономии в памяти не будет, а реализовывать потом разбор общей выборки --- только лишняя возня, которая в этом случае ничем не оправдывается

Fake_queen

действительно, все действительно очень "круто" и быстро ) спасибо )

Fake_queen

да, варианты не исключают друг друга, мне просто не хочется возится с сильным изменением кода, чтобы стало только одно обращение к файлу за всеми требуемыми подмассивами. да, и в проге уже реализован разбор этой кучи подмассивов.

evgen5555

Нет, не по-любому.
Сейчас попробовал, седовский вариант намного быстрее построчного.

pitrik2

Сейчас попробовал, седовский вариант намного быстрее построчного.
построчного или то которое было в изначальном варианте с загонением в память?
интересно почему сед быстрее
потому что он на Си написан что ли?

evgen5555

sed хавает файло кусками, как правило, большими, чем одна строчка

Bibi

разработчики sed'а, думаю, уже хорошо подумали над всеми возможными оптимизациями тех задач, которые он решает =)

Geddi-S

Нет, это побайтовое смещение.
Например, если файл - это числа вида x.xxx, после которых идет "\n" (то бишь 6 символов в итоге; если же "\r\n", то будет 7 то можно организовать такую вещь:

sub extract {
($name, $offset, $len)= @_;
open my $fh, '<', $name;
seek($fh, $offset*6, 0); # возможно, придется умножать на 7 - см. примечание выше
my (@mas, $str);
foreach (1..$len) {
read($fh, $str, 6); # возможно, придется ставить 7 - см. примечание выше
chomp($str);
push(@mas, $str);
}
close($fh);
return @mas;
}

На скорость не проверял, вполне возможно, что сед все равно рулит :)
Оставить комментарий
Имя или ник:
Комментарий: