Поиск элементов одного массива, отсутствующих в другом массиве  
Проблема
Требуется найти элементы, которые присутствуют в одном массиве, но отсутствуют в другом.
Решение
Мы ищем элементы @А, которых нет в @В. Постройте хэш из ключей @В — он будет использоваться в качестве 
таблицы просмотра. Затем проверьте каждый элемент @А и посмотрите, присутствует ли он в @В.
Простейшая реализация
# Предполагается,что @А и @В уже загружены
%seen = ();        # Хэш для проверки принадлежности элемента В
@aonly = ();       # Ответ
# Построить таблицу просмотра
foreach $item (@B) { $seen{$item} = 1 }
# Найти элементы @А, отсутствующие в @В
foreach $item (@A) {
  unless $item (@A) {
    # Отсутствует в %seen, поэтому добавить в @aonly
    push(@aonly, $item);
  }
}
Идиоматическая версия
my %seen;            # Таблица просмотра
my @aonly;           # Ответ
# Построить таблицу просмотра
@seen{(@В} = ();
foreach $item (@А) {
  push(@aonly, $item) unless exists $seen{$item);
}
Комментарий
Практически любая проблема, при которой требуется определить принадлежность скалярной величины к списку 
или массиву, решается в Perl с помощью хэшей. Сначала мы обрабатываем @В и регистрируем в кэше %seen все элементы @В, 
присваивая соответствующему элементу кэша значение 1. Затем мы последовательно перебираем все элементы @А и проверяем, 
присутствует ли данный элемент в хэше %seen (то есть в @В).
В приведенном фрагменте ответ будет содержать дубликаты из массива @А. Ситуацию нетрудно исправить, для этого 
достаточно включать элементы @А в %seen по мере обработки:
foreach $item (@A) {
  push (@aonly, $item) unless $seen{$item);
  $seen{$item) = 1;       # Пометить как уже встречавшийся
}
Эти решения в основном отличаются по способу построения хэша. В первом варианте перебирается содержимое @В. 
Во втором для инициализации хэша используется срез. Следующий пример наглядно демонстрирует срезы хэша. Фрагмент:
$hash{"key1"} = 1;
$hash{"key2"} = 2;
эквивалентен следующему:
@hash{"key1",   "key2"} = (1,2);
Список в фигурных скобках содержит ключи, а список справа — значения. В первом решении %seen инициализируется 
перебором всех элементов @В и присваиванием соответствующим элементам %seen значения 1. Во втором мы просто говорим:
@seen{@B}  = ();
В этом случае элементы @В используются в качестве ключей для %seen, а с ними ассоциируется 
undef, поскольку количество 
значений в правой части меньше количества позиций для их размещения. Показанный вариант работает поскольку 
мы проверяем только факт существования ключа, а не его логическую истинность или определенность. Но даже 
если с элементами @B потребуется ассоциировать истинные значения, срез все равно позволит сократить объем кода:
@seen{@B} = (1) x @B
См. также 
 
 
  Proverte kod v komentariyah gde pro list tam oshibki detskie
  
  
 
Оставить комментарий:
 |   
 |