Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

keys with an expression

by morgon (Curate)
on Nov 20, 2013 at 09:47 UTC ( #1063494=perlquestion: print w/replies, xml ) Need Help??
morgon has asked for the wisdom of the Perl Monks concerning the following question:


this is a way to get the unique elements of an array:

my @array = (1,1,2,3,2,2); my %temp = map { $_ => 1 } @array; my @unique = keys %temp;
I would like to do away with the temporary hash and would like to write the following seemingly natural perl-code:

my @unique = keys (map { $_ => 1 } @array);
But to my amazement this does not work with 5.18.1 - the error is "Type of argument to keys on reference must be unblessed hashref or arrayref".

I could swear this used to work some years ago (not really sure), so my question is how can I do this - how can I use keys with such an expression?

Is there really no way to avoid the ugly temporary?

Please note that the above is just an illustration - this is not a question about how to find unique array elements but a question concerning the kinds of expressions I can feed into keys.

Replies are listed 'Best First'.
Re: keys with an expression
by hdb (Prior) on Nov 20, 2013 at 09:49 UTC

    This should work in the newer Perls:

    my @unique = keys { map { $_ => 1 } @array };
Re: keys with an expression (List::AllUtils::uniq
by Anonymous Monk on Nov 20, 2013 at 10:08 UTC

    create a hash,ref { }

    dereference same hash,ref %{ { } }

    keys likes it

    use Data::Dump; dd( keys %{{ map { $_,1 } 1,2,1,2,1,4 }} ); __END__ (4, 1, 2)

    List::AllUtils :)

Re: keys with an expression
by tobyink (Abbot) on Nov 20, 2013 at 12:57 UTC

    This does create a temporary hash, but avoids the need to choose a name for the hash:

    my @items = qw( foo bar bar baz quux baz ); my @unique = local(*_) && grep(!$_{$_}++, @items); print "$_\n" for @unique;
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: keys with an expression
by lune (Monk) on Nov 20, 2013 at 15:04 UTC
    I don't know if that worked before, but I do find the error message okay, as
    (map { $_ => 1 } @array)
    returns a list, not an array, which "keys" would also accept as a valid argument.

    You get the same error if you try:

    my @unique = keys (1,1,2,3,2,2);

    but not with:
    my @unique = keys @array;
    which returns the indices of the array.
Re: keys with an expression
by AnomalousMonk (Canon) on Nov 20, 2013 at 19:16 UTC
    ... this is ... a question concerning the kinds of expressions I can feed into keys.

    Answers to questions like this can be had by Reading about keys and other, er, keywords (and much else besides) in The Fine Manual(s). (And BTW: Feeding keys et al a hash/array reference works from 5.14 on.)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1063494]
Approved by Corion
[ambrus]: Ok, so Prima has a postscript-like coordinate system
[Corion]: ambrus: Yes, which kinda makes sense because Prima also has Postscript output or something, I think

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2016-12-09 10:49 GMT
Find Nodes?
    Voting Booth?
    On a regular basis, I'm most likely to spy upon:

    Results (150 votes). Check out past polls.