开发者

How to copy keys from hash to array without duplicates?

开发者 https://www.devze.com 2023-03-17 04:49 出处:网络
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/;

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?


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;      
}


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

use List::MoreUtils qw( uniq );

@a = uniq @a, keys %h;


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

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


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;
0

精彩评论

暂无评论...
验证码 换一张
取 消