in reply to using map to generate a hash of hash

If the intent really is to do the hash assignment in one swoop, with exactly one map, then the key to your solution probably lies in restructuring your regex match, so that it produces one list item per intended hash item.

Can you show your current regex?

You might also want to show more realistic data. E.g. I can't tell if those "a", etc. are really one literal character, as shown, or if those are placeholders for longer, variable patterns. If the former, you should be able to do this:     /(abcd)/g Then your map could look like this:

map { my( $a, $b, $c, $d ) = split //; $a => { something => $b, another => $c } }
But I suspect that your situation is actually rather more complicated than that.

Replies are listed 'Best First'.
Re: Re: using map to generate a hash of hash
by Sihal (Pilgrim) on Nov 07, 2002 at 14:45 UTC
    Yes, you're correct, my situation is more complicated.

    here is the string i'm matching:
    4913|@rt Pages Photos|Paris 19|75019|31 Ave Secretan

    Where the a,b,c,d are the strings beetween the pipes. Of course, there are about 500 different stores that I wanna match in my string

    The regex:
    ($content =~ m/^(\d+) \| ([^\|]+) \| ([^\|]+) \| (\d\d\d\d\d) \| (.+) + /xg)
    And I don't mind using more than one map,I'd just like to do it in as little lines as possible.

    Thanks a lot for the help.
      Is each one of these records on a line by itself?
      If so, then you want either to read the input line by line, or split the content on newlines first.

      And then you probably want to use split rather than a regex, to parse each record.

      Example:

      my %hash = map { my( $a, @b ) = split /\|/; defined $a ? ( $a => { @b } ) : () } split /\n+/, $content;
      Also, I wonder what the subhashes are supposed to look like. Do you have a fixed set of keys, and only the values come from the input records? In that case, you could have something like this:
      my @subhash_keys = qw( something another ); my %hash = map { my( $a, @b ) = split /\|/; my %b; @b{ @subhash_keys } = @b; defined $a ? ( $a => \%b ) : () } split /\n+/, $content;
      Of course, ultimately, you may find it more convenient to use a more traditional for loop. It would also be more efficient for large input files.

      It's somewhat confusing that you keep talking of 4 pices of data s,b,c,d, however your sample string contains 4 pieces and your regex is capturing 5 peices?

      Also, in your original post, you show this

      $hash{'a'}=[something=>'b',another=>'c' ]

      which is assigns an array of 4 elements to the hash keyed by a, but the two of the 4 elements are not any of b,c,d(or e?), and two are.

      Further, you show the construction of the hash using fat commas (=>) which is usually use for setting up a hash, but in the context of an anonymous array [], means exactly the same (but in a confusing way) as an ordinary comma ','.

      I think some clarification is required here.


      Nah! You're thinking of Simon Templar, originally played (on UKTV) by Roger Moore and later by Ian Ogilvy
        the assignement error is a typo, sorry.

        Still on a rush but when things settle down I'll post some clarifications.