@Yestestvenno
Системный администратор

Perl как ускорить работу скрипта?

Нужно сравнить каждий елемент первого масива с каждым елементом второго и вывести на печать уникальные и не уникальные значения в разные файлы

#!/usr/bin/perl
.....
foreach $nn (@array0) {
$g=0;
foreach $mm (@array1) {
if ($nn==$mm) {
$g=$g+1
print FILE1 "$nn\n";
}
}
if ($g==0) {
print FILE2 "$nn\n";
}
}
.......
Как ускорить работу скрипта? обработка 10 000 х 1 000 000 = 10мин
а нужно сравнить примерно 1 000 000 000 х 1 000 000 000 000...... подскажите подход

Если использовать for то 10 000 х 1 000 000 = 37 мин

Уточняю
Сравнение не сильно замедляет.....
я запустил вот такую программу без сравнения:
foreach $nn (@array0) {
foreach $mm (@array1) {
$g=$g+1
}
}
в итоге время работы почти 10 мин
как можна сравнить значения по другому, не через foreach или for?
  • Вопрос задан
  • 429 просмотров
Решения вопроса 2
@pcdesign
Можно воспользоваться готовым модулем:
search.cpan.org/~zmij/Array-Utils-0.5/Utils.pm
Модуль быстрый.
Примерно так.
Есть два массива. Сравниваем их и выводим уникальные значения:
my @a = qw( a b c d );
my @b = qw( c d e f );
my @c = array_diff( @a, @b );
say for (@c)

Результат:
a
b
e
f


Теперь находим элементы не уникальные.
use feature 'say';
use Array::Utils qw(:all);


my @a = qw( a b c d );
my @b = qw( c d e f );
my @c = intersect( @a, @b );
say for (@c)


Результат

c
d
Ответ написан
vaut
@vaut
Совет дилетанта:
Меньшим списком заполняем хеш, и в один проход и большого получаем уников и дубли.
Забираем дубли в новый хеш и из меньшего списка получаем уников.
На небольших числах должно летать, упадет ли производительность на 10^6 записей не знаю.
Если будет падать меньший список нужно будет порезать на несколько.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
parserpro
@parserpro
1. Простые и быстрые алгоритмы есть в Perl Cookbook
2. Массивы размером миллиард и триллион элементов так не сравнить - памяти просто не хватит.
3. Какой тип данных? Понятно что в Perl это вроде не так важно, но для решения задачи значение имеет.

Навскидку решение:
Допустим что у нас только целые числа - значения от 0 до 65535. Построим битовую маску имеющихся в массиве чисел, причем если число есть - соответствующий ему бит выставим в 1. Размер маски очевидно 65536 бит или 8192 байта, что совсем и не много.
Итак, идем по первому массиву и заполняем маску.
Теперь идем по второму массиву и если бит в маске для текущего числа выставлен в 1, то число не уникально.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы