У меня есть два текстовых файла, которые содержат колоночные данные разнообразия position
-value
, отсортированный по position
.
Вот пример первого файла (файл A
):
100 1
101 1
102 0
103 2
104 1
...
Вот пример второго файла (B
):
20 0
21 0
...
100 2
101 1
192 3
193 1
...
Вместо того, чтобы читать один из этих двух файлов в хеш-таблицу, которая препятствует из-за ограничений памяти, что я хотел бы сделать, идти через два файла одновременно, пошаговым способом.
То, что это означает, - то, что я хотел бы передать потоком через строки также A
или B
и сравните position
значения.
Если эти два положения равны, то я выполняю вычисление на значениях, связанных с тем положением.
Иначе, если положения не равны, я перемещаюсь через строки файла A
или файл B
пока положения не равны (когда я снова выполняю свое вычисление), или я достигаю EOF обоих файлов.
Существует ли способ сделать это в Perl?
Похоже на проблему, на которую можно было бы наткнуться, например, данные таблицы базы данных с ключами и значениями. Вот реализация псевдокода, предоставленного rjp.
#!/usr/bin/perl
use strict;
use warnings;
sub read_file_line {
my $fh = shift;
if ($fh and my $line = <$fh>) {
chomp $line;
return [ split(/\t/, $line) ];
}
return;
}
sub compute {
# do something with the 2 values
}
open(my $f1, "file1");
open(my $f2, "file2");
my $pair1 = read_file_line($f1);
my $pair2 = read_file_line($f2);
while ($pair1 and $pair2) {
if ($pair1->[0] < $pair2->[0]) {
$pair1 = read_file_line($f1);
} elsif ($pair2->[0] < $pair1->[0]) {
$pair2 = read_file_line($f2);
} else {
compute($pair1->[1], $pair2->[1]);
$pair1 = read_file_line($f1);
$pair2 = read_file_line($f2);
}
}
close($f1);
close($f2);
Надеюсь, это поможет!
Для перебора файлов вы можете использовать модуль core Tie :: File . Он представляет собой обычный текстовый файл в виде массива.
Если файлы отсортированы, пройдитесь по ним, основываясь на том, какой из них имеет более низкую позицию.
Псевдокод:
read Apos, Aval from A # initial values
read Bpos, Bval from B
until eof(A) or eof(B)
if Apos == Bpos then
compare()
read Apos, Aval from A # advance both files to get a new position
read Bpos, Bval from B
fi
if Apos < Bpos then read Apos, Aval from A
if Bpos < Apos then read Bpos, Bval from B
end
Вы также можете использовать join(1), чтобы выделить строки с общими позициями и обработать их на досуге.