Re: using map to generate a hash of hash
by jdporter (Paladin) on Nov 07, 2002 at 14:33 UTC
|
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.
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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
| [reply] [d/l] |
|
|
Re: using map to generate a hash of hash
by thraxil (Prior) on Nov 07, 2002 at 14:27 UTC
|
But I don't understand how to take my 4 values and dump them in my hash, since map goes on 1 element of the list at a time....
that's about right. someone clever might be able to come up with a way to do what you want using map, but really that's the wrong tool for the job. a simple for loop would work much better and probably be clearer.
anders pearson
| [reply] |
|
|
Well, I'm aware that I can do that more easily using a loop but I'm very curious to find out if and how this can be solved with map.
| [reply] |
|
|
I'm sorry but an emergency is knocking on the door; so I can't reply to jdporter and dingus right now
However both of your posts are very interesting to me, I'll reply ASAP
| [reply] |
Re: using map to generate a hash of hash
by dingus (Friar) on Nov 07, 2002 at 15:00 UTC
|
As was stated by "jdporter on Nov 07, 2002 at 10:33" you pobably need to restructure the regex such that you can get all 4 variables in $1 $2 $3 (and $4 ?) and then you can do
while ($content =~ /(e)(x)(p)r/g) {
$hash{$1}={ something=>$2, another=>$3 } }
But assuming that the regex is NOT under your control and that you have in fact received from somewhere else a list of N items (where N is divisble by 4) and you wish to process the entire list without creating an intermedate array then the following will do the trick (and no doubt someone could rewrite this s.t. it uses map and is on one line):
my $c=0;
my @subkeys = ('', 'something', 'another', 'third');
my $k;
for ( split(/(?:box)?\n\s*/) ) {
if ($c) { ${$hash{$k}}}{$subkeys[$c]}=$_; }
else {$k = $_ }
$c = ($c + 1)%4;
}
I also note that you wrote [something=>'b',another=>'c' ] which is probably wrong. If you want a hash it should be { }, if you want an array then you don't need the 'something=>' bits.
Dingus Enter any 47-digit prime number to continue. | [reply] [d/l] [select] |
|
|
I'm sorry but an emergency is knocking on the door; so I can't reply to jdporter and dingus right now
However both of your posts are very interesting to me, I'll reply ASAP
| [reply] |