2

If I have an array and hash like these

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

my @a = qw/a b c d e/;
my %h = (a => 1, b => 1, f => 1, g => 1);

and I would like to end up with @a containing all of the keys from %h, and no element in the array must appear more than once.

How can that be done, as exists doesn't work on arrays?

4 Answers 4

6

If you have Perl 5.10 and later, you can use smart matching (~~):

for my $key (keys %h) {        
    push @a, $key unless $key ~~ @a;      
}

Otherwise, List::Util's first can help:

for my $key (keys %h) {        
    push @a, $key unless first { $_ eq $key } @a;      
}
Sign up to request clarification or add additional context in comments.

Comments

5

You could make use of List::MoreUtils's uniq function:

use List::MoreUtils qw( uniq );

@a = uniq @a, keys %h;

2 Comments

This is a union of @a and keys %h; she may have wanted an intersection?
I do not think that she intended an intersection. Relevant section: @a containing all of the keys from %h.
5

Convert the values you want into hash keys, then extract them

my %foo = map { $_ => 1  } @a, keys %h;
print sort keys %foo;

1 Comment

Or just @a = keys %{{ map {$_ => 1} @a, keys %h }}
4

How about this (admittedly destructive to `%h):

delete @h{ @a }; # delete all keys of h already in @a
push @a, keys %h; # push remaining keys onto @a

Thus @a retains the order it had and simply appends the non-duplicate keys in %h.

A word about the destructiveness: The example above illustrates some concepts of what can be done when you can afford to be destructive. And delete is certainly no more destructive than passing out of the scope of a lexical variable.

The issue can be addressed by simply copying it to another hash before narrowing the hash to those keys not found in @a.

my %h2 = %h;
delete @h2{ @a };
push @a, keys %h2;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.