I'd like to create an array of unique values

Discussion in 'Perl Misc' started by Mr P, May 9, 2007.

  1. Mr P

    Mr P Guest

    Sounds just like keys %h don't it.

    Starting with

    $_ =
    "cat
    man
    dog
    mouse
    man
    man
    ";

    I want to end up with

    [cat man dog mouse]

    My approach is:

    my @s = split /\n/;
    # unique-afy it!
    my %s;
    @s{@s} = @s;
    @s = keys %s;

    My PREFERENCE is to not have to involve both a hash and an array, and
    also to not have to include a non-native lib module.

    Is there a syntax I can use to just work with the hash and populate
    the keys-only directly from the split? I don't really care what the
    values are. I don't even care if they are undef.


    Thank-You, Peristas,

    MP
     
    Mr P, May 9, 2007
    #1
    1. Advertising

  2. Mr P

    Greg Bacon Guest

    In article <>,
    Mr P <> wrote:

    : Is there a syntax I can use to just work with the hash and populate
    : the keys-only directly from the split? I don't really care what the
    : values are. I don't even care if they are undef.

    You can condense your code a little:

    my %seen;
    my @s = grep !$seen{$_}++, split /\n/;

    Hope this helps,
    Greg
    --
    When government forces people to help their neighbors, conscience
    atrophies. When people are free to choose whether to help their
    neighbors or not, conscience is strengthened.
    -- Jacob G. Hornberger
     
    Greg Bacon, May 9, 2007
    #2
    1. Advertising

  3. Mr P

    Paul Lalli Guest

    On May 9, 11:29 am, Mr P <> wrote:
    > Sounds just like keys %h don't it.
    >
    > Starting with
    >
    > $_ =
    > "cat
    > man
    > dog
    > mouse
    > man
    > man
    > ";
    >
    > I want to end up with
    >
    > [cat man dog mouse]
    >
    > My approach is:
    >
    > my @s = split /\n/;
    > # unique-afy it!
    > my %s;
    > @s{@s} = @s;
    > @s = keys %s;
    >
    > My PREFERENCE is to not have to involve both a hash and an array, and
    > also to not have to include a non-native lib module.
    >
    > Is there a syntax I can use to just work with the hash and populate
    > the keys-only directly from the split? I don't really care what the
    > values are. I don't even care if they are undef.


    I don't think you're going to get around using both a hash and an
    array, without some serious mumbo-jumbo involving repeatedly looping
    through the array as you're building it. That will be unreadable and
    inefficient.

    The "right" answer is:
    my %h = map { $_ => 1 } split /\n/, $_;
    my @s = keys %h;

    If you're worried about having too many named variables, however, you
    could sacrifice some readability by making the hash anonymous:

    my @s = keys %{ {map { $_ => 1 } split /\n/, $_} };

    Perhaps you should be asking yourself why you're making this
    constraint, however.

    Paul Lalli
     
    Paul Lalli, May 9, 2007
    #3
  4. >>>>> "P" == P <> writes:

    P> my @s = split /\n/;
    P> my %s;
    P> @s{@s} = @s;
    P> @s = keys %s;

    P> My PREFERENCE is to not have to involve both a hash and an
    P> array, and also to not have to include a non-native lib module.

    Well, those are your two options.

    You can use a hash and an array, or you can include a non-core module.

    P> Is there a syntax I can use to just work with the hash and
    P> populate the keys-only directly from the split? I don't really
    P> care what the values are. I don't even care if they are undef.

    my %s;
    $s{$_}++ foreach (split /\n/);
    keys %s;

    Note that you're not really eliminating the array, though -- you're
    just using it implicitly in the foreach loop.

    Charlton




    --
    Charlton Wilbur
     
    Charlton Wilbur, May 9, 2007
    #4
  5. Mr P wrote:
    > Sounds just like keys %h don't it.
    >
    > Starting with
    >
    > $_ =
    > "cat
    > man
    > dog
    > mouse
    > man
    > man
    > ";
    >
    > I want to end up with
    >
    > [cat man dog mouse]
    >
    > My approach is:
    >
    > my @s = split /\n/;
    > # unique-afy it!
    > my %s;
    > @s{@s} = @s;
    > @s = keys %s;
    >
    > My PREFERENCE is to not have to involve both a hash and an array, and
    > also to not have to include a non-native lib module.
    >
    > Is there a syntax I can use to just work with the hash and populate
    > the keys-only directly from the split? I don't really care what the
    > values are. I don't even care if they are undef.


    $ perl -le'
    $_ =
    "cat
    man
    dog
    mouse
    man
    man
    ";

    my @s = do {
    my %unique;
    grep !$unique{$_}++, split /\n/;
    };

    print for @s;
    '
    cat
    man
    dog
    mouse



    John
    --
    Perl isn't a toolbox, but a small machine shop where you can special-order
    certain sorts of tools at low cost and in short order. -- Larry Wall
     
    John W. Krahn, May 9, 2007
    #5
  6. Mr P

    Mirco Wahab Guest

    Mr P wrote:
    > Starting with
    > $_ =
    > "cat
    > man
    > ...
    > [cat man dog mouse]
    >
    > My approach is:
    > ...
    > My PREFERENCE is to not have to involve both a hash and an array, and
    > also to not have to include a non-native lib module.
    >
    > Is there a syntax I can use to just work with the hash and populate
    > the keys-only directly from the split? I don't really care what the
    > values are. I don't even care if they are undef.



    The closest I could come up with is
    a simple match against a code assertion:

    ....

    my %h;
    $_ ='
    cat
    man
    dog
    mouse
    man
    man
    ';

    () = /(\w+)(?{$h{$1}=undef})/g;

    print " [@{[keys %h]}]";

    ....

    but I couldn't get your correct order ;-)

    Regards

    M.
     
    Mirco Wahab, May 9, 2007
    #6
  7. Mr P

    Mirco Wahab Guest

    Mirco Wahab wrote:
    > print " [@{[keys %h]}]";


    Stupid, because the hash slice *does*
    already provide list context, so a simple:


    @h{/(\w+)/g} = undef;

    print " [@{[keys %h]}]";


    would be all what's necessary.
    (did too much php lately ;-)

    Regards

    M.
     
    Mirco Wahab, May 9, 2007
    #7
  8. Mr P wrote:
    > Starting with
    > $_ =
    > "cat
    > man
    > dog
    > mouse
    > man
    > man
    > ";
    >
    > I want to end up with
    >
    > [cat man dog mouse]
    >
    > My approach is:
    >
    > my @s = split /\n/;
    > # unique-afy it!
    > my %s;
    > @s{@s} = @s;


    You can split() directly into a hash slice without reading the words into an
    array first:

    @s{split/\n/} = undef;

    > @s = keys %s;


    But that doesn't save you from still using keys() to get the list of unique
    words.

    jue
     
    Jürgen Exner, May 9, 2007
    #8
  9. Mr P

    Jorge Guest

    On May 9, 8:29 am, Mr P <> wrote:
    > Sounds just like keys %h don't it.
    >
    > Starting with
    >
    > $_ =
    > "cat
    > man
    > dog
    > mouse
    > man
    > man
    > ";
    >
    > I want to end up with
    >
    > [cat man dog mouse]
    >
    > My approach is:
    >
    > my @s = split /\n/;
    > # unique-afy it!
    > my %s;
    > @s{@s} = @s;
    > @s = keys %s;
    >
    > My PREFERENCE is to not have to involve both a hash and an array, and
    > also to not have to include a non-native lib module.
    >
    > Is there a syntax I can use to just work with the hash and populate
    > the keys-only directly from the split? I don't really care what the
    > values are. I don't even care if they are undef.
    >
    > Thank-You, Peristas,
    >
    > MP


    using arrays only --

    my @arr = qw(cat man dog mouse man man);

    my $prev = 'none';

    my @sorted_arr = sort(@arr);

    my @uniq_arr = grep($_ ne $prev && ($prev = $_), @sorted_arr);

    foreach my $uniq(@uniq_arr){
    print $uniq, "\n";
    }

    cat
    dog
    man
    mouse
     
    Jorge, May 9, 2007
    #9
  10. On May 9, 5:28 pm, Mirco Wahab <> wrote:

    > @h{/(\w+)/g} = undef;


    That is a list assignment so the RHS evaluates to a list containing a
    single undef element.

    Although that would work (as would _any_ list) it would be more
    idiomatic to write:

    @h{/(\w+)/g} = ();
     
    Brian McCauley, May 10, 2007
    #10
  11. Mr P

    Guest

    On May 9, 8:29 pm, Mr P <> wrote:
    > Sounds just like keys %h don't it.
    >
    > Starting with
    >
    > $_ =
    > "cat
    > man
    > dog
    > mouse
    > man
    > man
    > ";
    >
    > I want to end up with
    >
    > [cat man dog mouse]
    >
    > My approach is:
    >
    > my @s = split /\n/;
    > # unique-afy it!
    > my %s;
    > @s{@s} = @s;
    > @s = keys %s;
    >
    > My PREFERENCE is to not have to involve both a hash and an array, and
    > also to not have to include a non-native lib module.
    >
    > Is there a syntax I can use to just work with the hash and populate
    > the keys-only directly from the split? I don't really care what the
    > values are. I don't even care if they are undef.
    >
    > Thank-You, Peristas,
    >
    > MP



    I feel this is the shortest answer to ur query.

    perl -e '$_ = "dog
    man
    dog
    cat
    mouse
    man
    man";
    my %tmp; my @a;
    @a = map {$tmp{$_}=$_ if(! $tmp{$_});} split("\n",$_);
    print @a;'
     
    , May 11, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Klixx0r
    Replies:
    1
    Views:
    2,153
    Gerbrand van Dieijen
    Dec 8, 2004
  2. ToshiBoy
    Replies:
    6
    Views:
    876
    ToshiBoy
    Aug 12, 2008
  3. Paul
    Replies:
    3
    Views:
    110
  4. alanbe
    Replies:
    15
    Views:
    208
    Michael Winter
    Jun 3, 2005
  5. Token Type
    Replies:
    9
    Views:
    384
    Chris Angelico
    Sep 9, 2012
Loading...

Share This Page