2012-06-01 3 views
2

Я ищу помощь в одном сенарио.Удалить запись из массива на основе пользовательского дублирующего значения

Требование:

Через некоторой проверку, я strored следующих видов стоимости в одном массиве.

@array_name = ("Rajesh","Raju","Ram","John","peter"); 

Теперь я знаю, из какой-то фон, что «Раджеш», «Ram», «питер», повторяющиеся записи, так что я бы ожидать, мой выход будет:

@array_name = ("Rajesh","Raju","John"); 
# or 
@array_name = ("Ram","Raju","John"); 
# or 
@array_name = ("peter","Raju","John"); 

Я сделал пример программы таких как ниже, но это меня не удовлетворяет ...

my $spcific_output =""; 
    my $output =""; 

    foreach my $name (@array_name) 
    { 
     if($name eq "Rajesh" || $name eq "Ram" || $name eq "peter") 
     { 
      $spcific_output = "Rajesh and Ram and peter"); 
     } 
     else 
     { 
      $output .= "My Name is $name"; 
     } 
    } 
    $output .= $spcific_output; 

Любой лучший способ достичь этого?

+0

Что делает ваш пример программы должны сделать с ожидаемым выходом? – flesk

ответ

2

Если вы используете v5.10 или выше, вы можете использовать смарт-согласование на массив с совпадающими именами:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Data::Dumper; 

my @names = qw(Rajesh Raju Ram John Peter); 
my @dupl = qw(Rajesh Ram Peter); 
my $seen; 

my @names = grep {$_ ~~ @dupl ? !$seen++ : 1} @names; 

print Dumper \@names; 

Выход:

$VAR1 = [ 
      'Rajesh', 
      'Raju', 
      'John' 
     ]; 

условие в grep оценивает !$seen++ если имя от @names находится в @dupl и сохраняет $_ только тогда, когда $seen равно 0. В противном случае оценивается 1 (true) и $_ сохранен.

2

С помощью Perl, когда вы хотите получить уникальные значения из какой-либо коллекции, подумайте о том, как вы можете использовать хэш, чтобы помочь вам автоматически свернуть дубликаты или, по крайней мере, помочь вам запомнить, какие значения вы уже видели. Например, см. How can I get the unique keys from two hashes? в разделе 4 часто задаваемых вопросов по Perl.

Ваш случай немного сложнее, потому что у вас есть наборы сменных имен, поэтому вы должны записать эту информацию.

sub add_names { 
    my $equivalent = shift; 

    for (@_) { 
    my @names = map lc, @$_; 
    for (@names) { 
     die "$0: overlap on name '$_'" if exists $equivalent->{$_}; 
     $equivalent->{$_} = \@names; 
    } 
    } 

    $equivalent; 
} 

Здесь $equivalent является ссылкой на хэш. После вызова

add_names $equivalent, [ qw/ Rajesh Ram peter/]; 

хэш будет иметь ключи 'rajesh', 'ram' и 'peter', значение которых все [ 'rajesh', 'ram', 'peter' ]. Структурирование этого способа означает, что мы можем получить полный набор имен независимо от того, с каким именем мы сталкиваемся в первую очередь.

Заметим также, что вы можете сложить несколько наборов имен в одном вызове, как в

add_names $equivalent, [ qw/ Rajesh Ram peter/], 
         [ qw/ Jim Bob Bubba/]; 

С именами наметил, теперь мы можем обработать список и сохранить первое имя из каждого набора, который мы найти. Для данного имени проверьте, видели ли мы его ранее или какие-либо его эквиваленты. Если мы его не увидели, сохраните имя и отметьте все эквиваленты, как видно.

sub remove_duplicates { 
    my $equivalent = shift; 

    my %seen; 
    my @uniques; 
    foreach my $name (@_) { 
    my $normal = lc $name; 
    unless ($seen{$normal}) { 
     push @uniques, $name; 
     ++$seen{$_} for @{ $equivalent->{$normal} }; 
    } 
    } 

    wantarray ? @uniques : \@uniques; 
} 

wantarray бит на дне является общей идиома Perl для адаптации возвращаемого значения к контексту вызова. Если вызывающий объект хочет массив, мы возвращаем массив. Если нет, мы возвращаем скаляр, а именно ссылку на наш массив уникальных имен.

Собираем все вместе делает

my $equivalent = {}; 
add_names $equivalent, [qw/ Rajesh Ram peter /]; 

my @array_name = ("Rajesh","Raju","Ram","John","peter"); 
print $_, "\n" for remove_duplicates $equivalent, @array_name; 

Выход:

Rajesh 
Raju 
John
Смежные вопросы