Выборка уникальных элементов из списка  
Проблема
Требуется удалить из списка повторяющиеся элементы — например, при построении списка из файла или на 
базе выходных данных некоей команды. Рецепт в равной мере относится как к удалению дубликатов при вводе, 
так и в уже заполненных массивах.
Решение
Хэш используется для сохранения встречавшихся ранее элементов, а функция 
keys — 
для их извлечения. Принятая в Perl концепция истинности позволит уменьшить объем программы и ускорить ее работу.
Прямолинейно
%seen = ();
@uniq =();
foreach $item (@list) {
  unless ($seen{$item}) {
    # Если мы попали сюда, значит, элемент не встречался ранее
    $seen{$item} = 1;
    push(@uniq, $item);
  }
}
Быстро
%seen = ();
foreach $item (@list)   {
  push(@uniq, $item) unless $seen{$item}++;
}
Аналогично, но с пользовательской функцией
%seen = ();
foreach $item (@list) {
  some_func($item) unless $seen{$item}++;
}
Быстро, но по-другому
%seen = ();
foreach $item (@list) {
  $seen{$item}++;
}
@uniq = keys %seen;
Быстро и совсем по-другому
%seen = ();
@unique = grep { ! $seen{$_)++ } @list;
Комментарий
Суть сводится к простому вопросу — встречался ли данный элемент раньше? Хэши идеально подходят для подобного поиска. 
В первом варианте («Прямолинейно») массив уникальных значений строится по мере обработки исходного списка, а для 
регистрации встречавшихся значений используется хэш.
Второй вариант («Быстро») представляет собой самый естественный способ решения подобных задач в Perl. Каждый раз, 
когда встречается новое значение, в хэш с помощью оператора ++ добавляется новый элемент. Побочный эффект состоит в том, 
что в хэш попадают нее повторяющиеся экземпляры. В данном случае хэш работает как множество.
Третий вариант («Аналогично, но с пользовательской функцией») похож на второй, однако вместо сохранения значения мы 
вызываем некоторую пользовательскую функцию и передаем ей это значение в качестве аргумента. Если ничего больше не требуется, 
хранить отдельный массив уникальных значений будет излишне.
В следующем варианте («Быстро, но по-другому») уникальные ключи извлекаются из хэша %seen лишь после 
того, как он будет полностью построен. Иногда это удобно, но исходный порядок элементов утрачивается.
В последнем варианте («Быстро и совсем по-другому») построение хэша %seen объединяется с извлечением уникальных 
элементов. При этом сохраняется исходный порядок элементов.
Использование хэша для записи значения имеет два побочных эффекта: при обработке длинных списков расходуется 
много памяти, а список, возвращаемый keys, не отсортирован в алфавитном или числовом порядке и не сохраняет порядок вставки.
Ниже показано, как обрабатывать данные по мере ввода. Мы используем 'who' для получения сведении о текущем списке 
пользователей, а перед обновлением хэша извлекаем из каждой строки имя пользователя:
# Построить список зарегистрированных пользователей с удалением дубликатов
%ucnt = ();
for ('who') {
  s/\s.*\n//;   # Стереть от первого пробела до конца строки
                # остается имя пользователя
  $ucnt{$_}++;  # Зафиксировать присутствие данного пользователя
}
# Извлечь и вывести уникальные ключи
@users = sort keys %ucnt;
print "users logged in: @users\n";
См. также 
 
 
  Proverte kod v komentariyah gde pro list tam oshibki detskie
  
  
 
Оставить комментарий:
 |   
 |