blink has asked for the wisdom of the Perl Monks concerning the following question:

Given the code below, I'd like to perform the join, only if the variable hasn't already been joined.

When I dump the hash that this script creates, the inner hash, "tapes" can have duplicate values. I'll post some output to illustrate. I want only unique (in this case) tape id's to be included.

#!/opt/openv/perl/bin/perl -w use strict; use Data::Dumper; use NBUX; my %images = bpimagelist(); #print Dumper(\%images); #exit; my (%status); foreach my $key (sort keys %images) { my ($tapes, $img); my $client = $images{$key}->{'client'}; my $sched_type = $images{$key}->{'schedule_type'}; my $sched_name = $images{$key}->{'sched_label'}; my $policy = $images{$key}->{'policy'}; my $kb = $images{$key}->{'kbytes'}; foreach my $key2 (sort keys %{$images{$key}}) { if ($key2 =~ /copy_\d_frag_\d_id/) { $img = $images{$key}{$key2}; $tapes = (join (' ', $img, $tapes)); $status{$client}{$policy}{'tapes'} = $tapes; } } } #print Dumper(\%status); #exit;
Here's some example output that I'm trying to avoid:
$VAR1 = { 'bondsrv1' => { 'acis_misc_os' => { 'tapes' => 'OK0238 OK0238 ' + } }, }

Replies are listed 'Best First'.
Re: Join unless $var has already been joined?
by sgifford (Prior) on Sep 23, 2003 at 20:58 UTC

    What you want is to eliminate duplicate elements from a list. Here's one solution, from the Perl cookbook (via RE: Return a Unique Array):

    my %seen =() ; @unique_array = grep { ! $seen{$_}++ } @non_unique_array ;

    Put that into a sub:

    sub dedup { my %seen; grep { ! $seen{$_}++ } @_; }
    and you can simply do
    @tapes = qw(tape1 tape2 tape1 tape3 tape2 tape1); print join(' ',dedup(@tapes)),"\n";
    to join tapes together with no duplicates.
Re: Join unless $var has already been joined?
by Roger (Parson) on Sep 24, 2003 at 00:29 UTC
    Replace your foreach loop with this instead -
    foreach my $key (sort keys %images) { my ($tapes, $img); my $client = $images{$key}->{'client'}; my $sched_type = $images{$key}->{'schedule_type'}; my $sched_name = $images{$key}->{'sched_label'}; my $policy = $images{$key}->{'policy'}; my $kb = $images{$key}->{'kbytes'}; # Create an array of tape records my @tapes; foreach (keys %{$images{$key}) { if (/copy_\d_frag_\d_id/) { push @tapes, $images{$key}{$_}; } } # Join tape id's in sorted order $status{$client}{$policy}{'tapes'} = join " ", sort keys %{{map {$_=>1} @tapes}}; }