Forum Webscript.Ru
Программирование => Perl => Тема начата: Phoinix от 09 Августа 2004, 18:09:11
-
Есть два массива, и нужно узнать сколько в них есть одинаковых элементов, возможно ли это вычислить проще чем
my @arr1 = (\'1\',\'2\',\'3\',\'4\',\'5\');
my @arr2 = (\'6\',\'1\',\'7\',\'5\',\'8\');
my $i;
foreach my $value (@arr2) {$i += grep{/$value/}@arr1}
print $i;
результат: 2
?
-
Один из массивов (желательно короткий) загнать в хеш, потом пробежаться по второму массиву.
-
КшЫуфксрук
...загнать в хеш...
Гм... а собственно зачем?
В общем-то а могу сразу формировать один из массивов в хеш (правда определить какой больше - не получится).
Тогда получается конструкция:
my @arr1 = (\'1\',\'2\',\'3\',\'4\',\'5\');
my %hash = {6 => 6, 1 => 1, 7 => 7, 5 => 5, 8 => 8};
my $i;
foreach my $value (@arr1) {$i++ if $hash{$value}}
print $i;
Но насколько это оптимальней?
-
Гм... а собственно зачем?
1. Так правильнее. Вот этот код тоже два выдает:
my @arr1 = (\'11\',\'2\',\'3\',\'4\',\'5\');
my @arr2 = (\'6\',\'1\',\'7\',\'5\',\'8\');
my $i;
foreach my $value (@arr2) {$i += grep{/$value/}@arr1}
print $i;
2. Есть подозрение, что на больших массивах будет гораздо быстрее.
-
КшЫуфксрук
Вот этот код тоже два выдает
Он выдает потому-что 11 ~ /1/, просто не поставил границы:
grep{/^$value$/}@arr1
Поэтому утверждение:
Так правильнее
Не совсем верно...
Есть подозрение, что на больших массивах будет гораздо быстрее
У меня вообщем-то предполагается, что размеры массивов не более 20 элементов каждый. Но для дальнейшего использования интересно получить более оптимально решение...
Основная цель - уйти от цикла (foreach).
-
Phoinix держи:
map { push (@m , $_) if $_{$_} > 1} grep{!$_{$_}++} @arr1, @arr2;
print $#m+1;
пояснять нужно?
-
Phoinix:
могу сразу формировать один из массивов в хеш
приветик. :)
если это будет хэш %h:
foreach (@arr) { $h{$_}=1; }
print scalar keys %h;
Phoinix:
нужно узнать сколько в них есть одинаковых элементов
-
NeoNox, «монстрите», как всегда. :)
поясните, пож-ста.
-
Phoinix
Для 20 элементов наверное нет особой разницы, как делать. Просто твой алгоритм крадратичный, а мой линейный. И зачем уходить от foreach не понятно.
NeoNox
Этот код работает немного не так, как исходный:
my @arr1 = (\'1\',\'2\',\'2\',\'4\',\'5\');
my @arr2 = (\'6\',\'1\',\'7\',\'5\',\'8\');
map { push (@m , $_) if $_{$_} > 1} grep{!$_{$_}++} @arr1, @arr2;
print $#m+1;
выдает "3", а исходный выдал бы "2".
-
AnnA:
поясните, пож-ста.
запросто.
1. grep{!$_{$_}++} @arr1, @arr2;
здесь формируется временный хеш и ему присваивается количество совпадений
2. map { push (@m , $_) if $_{$_} > 1}
а здесь при совпадении условия $_{$_} > 1 (нам нужно количество неуникальных элементов) заносим в третий массив.
Правда одно но:
мы грепаем по всем спискам, так что если будут совпадения в рамках одного массива - они тоже поместятся в @m.
-
NeoNox
Да уж... про повторы, я то и забыл, что можно просто вычислить количество совпадений, тем более, что элементы обоих массивов уникальны...
А тема как раз недавно поднималась... http://forums.webscript.ru/showthread.php?s=&postid=111769#post111769 (http://forums.webscript.ru/showthread.php?s=&postid=111769#post111769)
Спасибо...