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

OK, this probably falls into the realm of stupid questions, but I have a brain freeze here. What's the best way to convert the following:
1,2,3,4,5:one,two,three,four,five
into a hash where $hash{1}="one"?

I've thought of all sorts of stupid methods, like splitting into two arrays, etc., but I know there is a better way!

Thanks.

Replies are listed 'Best First'.
Re: creating a particular hash
by srawls (Friar) on Jun 01, 2001 at 02:26 UTC
    Well, this isn't a golf here, but here's a shot at what you want:
    $_ = '1,2,3,4,5:one,two,three,four,five'; @_ = split':',$_; @hash{split',',$_[0]}=split',',$_[1]; print $hash{1};


    The 15 year old, freshman programmer,
    Stephen Rawls
      Golf?! Did you say "golf"? How about unnecessarily obsfuscating it?
      sub o { # 1 2 3 4 5 6 # 12345678901234567890123456789012345678901234567890123456789012345678 + split/[,:]/,pop;$hash{$_[$_]}=$_[$_+$#_/2+1]for 0..$#_/2;%hash; }
(Ovid) Re: creating a particular hash
by Ovid (Cardinal) on Jun 01, 2001 at 02:38 UTC
    Actually, splitting it into two arrays is not a bad idea. While this is not as concise as the previous example, I think it's a bit clearer:
    my $string = '1,2,3,4,5:one,two,three,four,five'; my %results; my @vals = split /[:,]/, $string; if ( $#vals % 2 ) { for ( 0 .. int( $#vals/2 ) ) { $results{ $vals[ $_ ] } = $vals[ $_ + int( $#vals/2 ) + 1 ]; } }

    Umm... on second thought, maybe it's not :)

    Cheers,
    Ovid

    D'oh! Vynce pointed out the hash slice. Why do I always forget about 'em? :)

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      you already got lots of code answers, but not a lot of explanation, so i'll go light on the former and heavy on the latter.

      conceptually, it isn't bad to split it into two arrays, because you can then refer to a hash slice. given this:

      my %hash; my @keys = (1, 2, 3, 4, 5); # an array of hash keys my @values = qw(one two three four five); # array of values
      you can say
      @hash{@keys} = @values;
      that array prefix (@) tells perl you're going to be dealing with a list out of that hash, rather than a scalar. the array in the curlies ({}) tells perl what keys to use; @hash{@keys} is effectively the same as saying ($hash{$keys[0]}, $hash{$keys[1]}, $hash{$keys[2]}, ...). then you assign them all at once from the array of values; this works just like any list assignment.

      of course, you didn't start with those two arrays, so you have to make them in order to use them, but that's OK; the split statements shown will work, and you sounded like you knew how to do that anyway.

      .

      actually, if you really are using integer keys, you might want to consider putting them into an array rather than into a hash; it depends what else is going on. but

      @array[@keys] = @values
      will work just as well, for the example you've shown, and take much less memory.

      another handy thing to keep in mind is that you can use the range operator to create that list for you.

      @words_array[1..12] = qw(one two three four five six seven eight nine +ten eleven twelve); @words_hash{(1..12)} = qw(one two three four five six seven eight nine + ten eleven twelve);
      but now i'm sure i've digressed. for more information, look up array and hash slices. (Note: this deals more with multidimensional slices, but i couldn't find better documentation on straight slices.)

      update hash slices are forgettable; they read funny, they seem weird, and they're fundamentally useful. how's that for trouble? who would expect to be able to talk about a list of things from an unordered pile of associations? anyway, there are things i'd like hash slices to do that they don't.

        Wow, thanks for the explanation! Those hash slices are cool, and did just what I wanted them to.
Re: creating a particular hash
by runrig (Abbot) on Jun 01, 2001 at 02:46 UTC
      Don't you love how lisp made it's way into perl?

      Now if only there were also the beauties of cond...

        have you seen Switch?

        Also, because I am converting a lot of lisp and scheme code, I dont really like cond very much.

        In Perl, I can be much more concise:

        return undef if !$bindings ; return (extend $bindings) if (var_match $pattern) ; return pat_match(rest $input) if @$input ;
        The equivalent cond I do find a bit harder to follow.
Re: creating a particular hash
by MeowChow (Vicar) on Jun 01, 2001 at 05:51 UTC
    I don't have anything of value to add aside from this vile line of code...
    1 while s/^(.+?\b),?(.*):(.+?\b),?(.*)$/$hash{$1}=$3;"$2:$4"/e;
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
      I don't have anything really to add either, here's an ugly one as well:
      /(.*):(.*)/;@h{split',',$1}=split',',$2;
        I have something to add to that:
        /:/;@h{split',',$`}=split',',$';
        but this is __nasty__ and i do not advocate the use of $` or $' in anything but golf/obfu :)

        "Argument is futile - you will be ignorralated!"