Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Hash asignement with RE and map()

by bobione (Pilgrim)
on Jul 03, 2001 at 22:30 UTC ( #93620=perlquestion: print w/replies, xml ) Need Help??
bobione has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,
Here is my mystery:
I'd like to assign a hash to a "complexe" (read big) regular expression.

m/(ID)(name)(email)(title)(date)(...)/  # simplify

I know that I can do that:

(ID, name, email, title, date, ...) = /(ID)(name)(email)(title)(date)(...)/;

but I'd like to do something like that:

%hash{ID} = (name, email, title, date, ...) = map {/(ID)(name)(email)( +title)(date)(...)/} @lignes; # Get parameters for each line... Like CSV files. But ID is not in the + same list

Something better could be to use OObject but hey, I am lost...

I hope I am clear enougth,
help will be greetfully appreciate :)

BobiOne KenoBi ;)

Replies are listed 'Best First'.
(bbfu) Re: Hash asignement with RE and map()
by bbfu (Curate) on Jul 03, 2001 at 22:45 UTC

    my %hash = map { /(ID)(name)(email)(title)(date)(...)/ && do { ($1, [$ +2, $3, $4, $5, ...]) } } @lines; # or, equivalently: my %hash = map { ($1, [$2, $3, $4, $5, ...]) if(/(ID)(name)(email)(tit +le)(date)(...)/ } @lines;

    bbfu
    Seasons don't fear The Reaper.
    Nor do the wind, the sun, and the rain.
    We can be like they are.

      I would be inclined to write it as follows, so as to avoid the explicit enumeration of match groups:
      my %hash = map { shift @$_ => [ @$_ ] } map [ /(ID)(name)(email)(title)(date)(...)/ ], @lines;
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
Re: Hash asignement with RE and map()
by dragonchild (Archbishop) on Jul 03, 2001 at 22:43 UTC
    If I'm right, you've got some string which parses out into an ID, then a series of fields. You want to create a hash with key of ID and value being some hashref, pointing to a hash with key of name/email/etc and value being the value.

    The basic code for this would be something like:

    ($ID,$name,$email,$title,$date,...) = /(ID)(name)(email)(title)(date)( +...)/; $hash{$ID}{name} = $name; $hash{$ID}{email} = $email; ...

    Now, what you're doing is, essentially, assigning a hash slice. Now, if you don't know, a hash slice is done something like:

    my @keys = ('a', 'b', 'c'); my @vals = (1, 2, 3); my %hash; @hash{@keys} = @vals;

    At this point, $hash{a} == 1, etc.

    For a hash of hashes, I think the syntax is something like:

    my @keys = ('a', 'b', 'c'); my @vals = (1, 2, 3); my %hash; @($hash{key}}{@keys} = @vals;

    But, please test this out.

    To marry this with the code you have right now, I'd do something like:

    my @keys = ('name', 'email', 'title', ...); ($ID, @vals) = /(ID)(name)(email)(title)(date)(...)/; @{$hash{$ID}}{@keys} = @vals;
      Thank you for your explanation, it will be usefull.
      But bbfu got the hint ;)

      Thanks all ! This make it a bit clearer now.

      BobiOne KenoBi ;)

Re: Hash asignement with RE and map()
by John M. Dlugosz (Monsignor) on Jul 03, 2001 at 22:39 UTC
    my @results= m/ ... /; my $ID= shift @results; $hash{$ID}= [@results];
    Something like that?

    —John

(dkubb) Re: (2) Hash asignement with RE and map()
by dkubb (Deacon) on Jul 04, 2001 at 06:49 UTC

    Others in this node have outlined the technique, but I'd like to present the concept in the context of a working example:

    #!/usr/bin/perl -w use strict; use Data::Dumper qw(Dumper); my %hash; while (my $line = <DATA>) { next unless my ($id, @row) = $line =~ /^(\d+) (\w+) (\S+) (\w+) (\w+)$/; @{$hash{$id}}{qw(name email title date)} = @row; } print Dumper(\%hash); __DATA__ 1 merlyn merlyn@perlmonks.org saint today 2 tilly tilly@perlmonks.org saint today 3 tye tye@perlmonks.org saint today 4 jcwren jcwren@perlmonks.org saint today

    This will iterate over the file handle, and attempt to match the $line with a regex. (You'll note that I changed the regex slightly to work with the data) If there is no match, then it will skip over the line. If there is a match, it will assign to a hash slice underneath $hash{$id}. It's the equivalent of:

    my %hash; my %account; @account{ qw(name email title date) } = @row; $hash{$id} = \%account;

    One advantage of the first example is that you are doing it in a single step, without using any 'Synthetic' Code.

Re: Hash asignement with RE and map()
by thpfft (Chaplain) on Jul 03, 2001 at 23:05 UTC

    how about s///e? eg:

    s/(ID)(name)(email)(title)(date)(...)/%{$hash{$1}}=($2,$3,$4,$5)/ie for @lines;

    Or something like that. The exact form will depend on whether your re matches keys and values or just values.

    update: added caveat

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://93620]
Approved by root
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2018-07-16 05:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (332 votes). Check out past polls.

    Notices?