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

This code cuts out two keys/values... Any ideas?
use strict; my $names = " John 20, Bill 34, Jane 28, Wall 18, Tom 19"; print $names,"\n"; my %hash_list = sort(split (/,/, $names)); print %hash_list,"\n"; my @keys = sort { $hash_list{$a} cmp $hash_list{$b} } keys %hash_list; print %hash_list, "\n"; print @keys, "\n";

Replies are listed 'Best First'.
Re: Keys/Values being lost with this code--any help?
by lestrrat (Deacon) on Sep 24, 2002 at 03:52 UTC

    You are assigning the result of split() to a %hash

    ## your code is effectively this: my %hash_list = ( " Bill 34", " Jane 28", " John 20", " Tom 19", " +Wall 18" ); ## which means... my %hash_list = ( # key # value " Bill 34" => " Jane 28", " John 20" => " Tom 19", " Wall 18 => undef );

    Upon upon further inspection, if you just want to sort these in alphabetical order, you do not need to assign them to a hash... just use a simple sort, and you're done:

    print sort ( split( /,/, $names ) );

    However, if you want to sort them by, say, the number to the right of the name, then you do need to use a hash:

    my $names = "John 20, Bill 34... etc"; my @elems = split( /\s*,\s*/, $names ); my %num2name = map{ reverse split( /\s/, $_ ) } @elems; my @sorted = map{ $num2name{$_} } sort { $a <=> $b } keys %num2n +ame; print "@sorted\n";
Re: Keys/Values being lost with this code--any help?
by Zaxo (Archbishop) on Sep 24, 2002 at 04:05 UTC

    Your split is giving you the following list: ( ' John 20', ' Bill 34', ' Jane 28',' Wall 18', ' Tom 19'). Then when you sort and assign that list to a hash, it looks like:

    my %hash_list = ( ' Bill 34' => ' Jane 28', ' John 20' => ' Tom 19' , ' Wall 18' => );
    spliting on white space will fix things. A nicer data representation would help, but sometimes you have to work with what you get.

    After Compline,
    Zaxo

Re: Keys/Values being lost with this code--any help?
by tadman (Prior) on Sep 24, 2002 at 05:09 UTC
    When you're stumped by problems like this, it's helpful to use Data::Dumper to look at what data you have in your internal variables. Here's what I would do:
    my %hash_list = sort(split (/,/, $names)); use Data::Dumper; print Dumper(\%hash_list); # DEBUG
    The reason for the "DEBUG" comment is that I like to label my debugging lines so that later, I can grep for them to make sure there's no extraneous testing code left in. That's also why both statements are on one line.

    When you look at the result form this, it's pretty clear how your structure is broken. As a bonus, you get to see the extra space in your variables.
Re: Keys/Values being lost with this code--any help?
by dws (Chancellor) on Sep 24, 2002 at 04:15 UTC
    This code cuts out two keys/values... Any ideas?

    Looking at the code, it isn't instantly clear what you expect the keys and values to be. A case can be make for either of   ( "John" => 20, "Bill" => 34 ... ) or   ( "John 20" => ?, "Bill 34" => ?, ... ) To help your readers figure out your intent, it helps to give variables clear names. %hash_list is not a clear name. If you intend to map names to ages, %name_to_age is a decent choice. If you intend to count name+age strings, %name_and_age_count would reveal your intention unambiguously.

Re: Keys/Values being lost with this code--any help?
by dbp (Pilgrim) on Sep 24, 2002 at 06:21 UTC
    Did you mean this?
    my %hash_list = map { split ' ' } split(/,/, $names);
    This would creat a hash of the form:
    %hash_list = ( John => 20, Bill => 34, Jane => 28, Wall => 18, Tom => 19 );
      Thanks to all for your replies! This is what I was looking for. I must apologize for not being able to state what I needed in an understandable fashion. Please excuse me as I am still new to Perl and am just getting comfortable with the language! Thanks! PS: What would you use to sort this? Either by the key or by the value--which subroutines can be used? Thanks again.
        ## assuming my %hash = ( John => 20, Bill => 34, # etc... ); ## sort by name(key): foreach my $name ( sort keys %hash ) { print "$name: $hash{$name}\n"; } ## sort by number(value): foreach my $name ( sort { $hash{$a} <=> $hash{$b} } keys %hash ) { print "$name: $hash{$name}\n"; }