Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Putting an array into a hash

by Theo (Priest)
on Dec 10, 2004 at 05:55 UTC ( [id://413760]=perlquestion: print w/replies, xml ) Need Help??

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

I have some alumni data from which I need to extract useful info. To that end I'm trying to go from the native (pseudo)XML file to a key/value hash.
Before stripping out the excess XML tags the @info array has the full record of one person, a sample of which is in Listing 1. Listing 2 is printed by the code segment shown and the error message is below that.
I've preloaded %data hash just to be sure I can see if there are any changes in the hash.
I'd like to know what the error means, but the real question is how to transform an array into a hash.
The nature of this data is that the keys will all be unique.
(code being tested on a Win98 PC using Active State version 5.005_03)

########### Code Segment ############## my %data = (one => 1, two => 2, three => 3); : # XML stripped off here : print @info; # Prints Listing 2 print %data; # bottom of listing 2 %data = @info =~ /(\w+)\s*(\w+)/g; # Line that gives error print %data; # Prints nothing ####################################### ### Listing 1 ### <Position> Stdnt</Position> <GradYear> 1987</GradYear> <WebPage> http://</WebPage> <E-mail> SomeAddr@abc.com</E-mail> <Comments> Needs highschool yearbooks</Comments> ### Listing 2 ### Position Stdnt GradYear 1987 WebPage http:// Email SomeAddr@abc.com Comments Needs highschool yearbooks three3two2one1 ### Error message ### Applying pattern match to @array will act on scalar(@array) at e.pl li +ne 29

Due to the embedded spaces in some of the data, a better approach might be to strip the XML and create the hash in the same step, but not till I can get through this problem.

Update: Thank you Zaxo, saintmike and ysth. I'm still recovering from the first bout of flu I've had in 20 years and not thinking clearly. I'll put this to use in a few days. Again, thanks!

-Theo-      (so many nodes and so little time ... )

Replies are listed 'Best First'.
Re: Putting an array into a hash
by Zaxo (Archbishop) on Dec 10, 2004 at 06:09 UTC

    This should do the job, %data = map {/(\w+)\s*(\w+)/} @info; That will key the hash with the first word and place the next word as value. You may want to replace that with split ' ', $_, 2, so that punctuation in the data or multi-word values don't give mangled results. For instance, in your data, your regex will cut off the email address at the @ sign.

    %data = map {split ' ', $_, 2} @info;

    After Compline,
    Zaxo

Re: Putting an array into a hash
by saintmike (Vicar) on Dec 10, 2004 at 06:09 UTC
    You don't want to apply the pattern match to an array -- you want to apply it to every element:
    %data = map { /(\w+)\s*(\w+)/; ($1, $2) } @info;
      Thanks to the observations of Zaxo and you, I've gotten through some errors, misunderstandings and typos, but there is one error message I don't understand (even with use diagnostics). The whole program follows with the error listed first. The line giving the error is the one with the map command. It looks like the variables $1, $2 are somehow not being set. Perhaps the oddest aspect is that the program seems to work anyway. The error message is repeated 3 times.

      Error:
      Use of uninitialized value at e.pl line 13, <DATA> chunk 5.

      Code:
      #!/usr/bin/perl -w my $file; my @info; my $line; my %data = (one => 1, two => 2, three => 3); foreach $file (<BXML=Tr*>) { open (DATA, $file); @info = <DATA>; # @info contains the whole xml record foreach $line (@info) { chomp $line; $line =~ s|E-mail|Email|g; # make email tags match all other + tags %data = map { /<(\w+)>\s*(.*?)<\/\w+>/; ($1, $2) } @info; } print "\n",$data{"Position"},"\t",$data{"GradYear"},"\t",$data{"Em +ail"},"\n"; } close (DATA);
      OutPut:
      Stdnt 1987 SomeAddr@abc.com

      So, can I safely ignore the error since the code does what I expect? Or is that asking for trouble?

      -Theo-      (so many nodes and so little time ... )

Re: Putting an array into a hash
by ysth (Canon) on Dec 10, 2004 at 12:54 UTC
    I'd like to know what the error means, but the real question is how to transform an array into a hash.
    ...
    %data = @info =~ /(\w+)\s*(\w+)/g;    # Line that gives error
    ...
    Applying pattern match to @array will act on scalar(@array) at e.pl line 29
    You can get more information on any error by putting "use diagnostics;" in your script (or looking up the error via perldoc perldiag or the splain utility).
    $ echo 'Applying pattern match to @array will act on scalar(@array) at + e.pl lin e 29'|splain|fmt Applying pattern match to @array will act on scalar(@array) at e.pl li +ne 29 (#1) (W misc) The pattern match (//), substitution (s///), and transliteration (tr///) operators work on scalar values. If you apply one of them to an array or a hash, it will convert th +e array or hash to a scalar value -- the length of an array, or the population info of a hash -- and then work on that scalar value. This is probably not what you meant to do. See perlfunc/grep and perlfunc/map for alternatives.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://413760]
Approved by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-03-29 04:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found