Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Manipulating data structure

by SerZKO (Beadle)
on Aug 16, 2012 at 09:26 UTC ( #987716=perlquestion: print w/ replies, xml ) Need Help??
SerZKO has asked for the wisdom of the Perl Monks concerning the following question:

Hej Monks,

I have a following data structure :

UID= UID=FRLARS UID=ANJA08 FNA= FNA=Fredrik FNA=Anja ENA=Exp-pri ENA=Larsson ENA=Daun PRE=(0117) PRE=(0117) PRE=(0117) NYTT=23400 NYTT=23403 NYTT=23404 PRI1=Nej FOR1=Nej DOL1=Nej CMG1=Ja MEX1=Nej PRI2=Nej FOR2=Nej DOL2=Nej CMG2=Ja MEX2=Nej PRI3=Nej FOR3=Nej DOL3=Nej CMG3=Ja MEX3=Nej
as a result of a web form. Now, is it possible to get this data out in a "csv" format having in mind that number of records can differ which means that "x" in last part (PRIx, FORx, DOLx, CMGx, MEXx) will increase depending on how many UIDs there are ?

I've tried with following :
my @entries; my $previouskey = ""; open (KOF, "<$konfil") or die "Kan inte \xF6ppna filen $konfil"; open (NYF, ">$nyfil") or die "Kan inte \xF6ppna filen $nyfil"; flock (NYF,2) or die $!; my $offset = 0; while(<KOF>) { chomp; $value =~ s/^\s*(\S*)\s+$/$1/; unless ($key eq $previouskey || $previouskey eq "") { $offset = 0; } $previouskey = $key; $entries[$offset]{$key} = $value; $offset++; } my @sorted = sort { $a->{'NYTT'} <=> $b->{'NYTT'} } @entries; my $pers =0; foreach my $e (@sorted) { print NYF ($e->{'UID'}, "|", $e->{'FNA'}, "|", $e->{'ENA'}, "|", $ +e->{'PRE'}, "|", $e->{'NYTT'}, "\n") if( $e->{"UID"} ne "" || $e->{"F +NA"} ne "" || $e->{"ENA"} ne ""); $pers++ if ($e->{"UID"} ne ""); } close KOF; close NYF;
and it seems to work fine, but I just don't know how to add now last part that changes numbers in the name.

Thanks in advance for your help

Comment on Manipulating data structure
Select or Download Code
Re: Manipulating data structure
by Ratazong (Prior) on Aug 16, 2012 at 09:51 UTC

    Hi SerZKO!

    Your hash-key does not need to be a static string, but could be constructed on the fly with a variable containing a counter. Check the following example

    my %e; my $max = 4; foreach my $nr (1..$max) { $e{"uid_$nr"} = $nr; }
    For your problem, you may either add a the number of available UIDs in your data-structure (and use it like the $max in the example above), or you might check with exists whether a specific UID-entry is present in your hash (e.g. if (exists($e{"MEX$nr"}) { ... })

    HTH, Rata
      Hej Rata and thanks for your reply,

      I've modified my code like this :

      my @entries; my $previouskey = ""; open (KOF, "<$konfil") or die "Kan inte \xF6ppna filen $konfil"; open (NYF, ">$nyfil") or die "Kan inte \xF6ppna filen $nyfil"; flock (NYF,2) or die $!; my $offset = 0; while(<KOF>) { chomp; $value =~ s/^\s*(\S*)\s+$/$1/; unless ($key eq $previouskey || $previouskey eq "") { $offset = 0; } $previouskey = $key; $entries[$offset]{$key} = $value; $offset++; } my @sorted = sort { $a->{'NYTT'} <=> $b->{'NYTT'} } @entries; my $pers =0; my $Za=1; #####Added foreach my $e (@sorted) { print NYF ($e->{'UID'}, "|", $e->{'FNA'}, "|", $e->{'ENA'}, "|", $ +e->{'PRE'}, "|", $e->{'NYTT'}, "|", $e->{"PRI$Za"}, "|", $e->{"FOR$Za +"}, "|", $e->{"CMG$Za"}, "|", $e->{"MEX$Za"}, "\n") if( $e->{"UID"} n +e "" || $e->{"FNA"} ne "" || $e->{"ENA"} ne ""); $pers++ if ($e->{"UID"} ne ""); $Za++; #####Added } close KOF; close NYF;
      but I only get result on first line with all others empty ? Like this:
      ||Exp-pri|(0117)|23400|Nej|Nej|Ja|Ja|Nej FRLARS|Fredrik|Larsson|(0117)|23403||||| ####Empty ANJA08|Anja|Daun|(0117)|23404||||| ####Empty

      What could go wrong ? It only interpolates variable PRI and adds a number ?
Re: Manipulating data structure
by sundialsvc4 (Monsignor) on Aug 16, 2012 at 12:56 UTC

    This puzzles me slightly, because it appears to just be a POST data-stream which any of several CGI-handling packages already know how to handle.   But, nevertheless, the so-called “auto-vivification” features of Perl make such things much easier than what you seem to be doing here.   Consider the following one-liner:

    perl -e 'my $foo; push @{$$foo{'bar'}}, 3; use Data::Dumper; print Data::Dumper->Dump([\$foo],["foo"]);' $foo = \{ 'bar' => [ 3 ] };

    As you can see:

    • merely by using a key {'foo'}, Perl causes $foo to automatically become defined as a hash.   (Notice how in this case it was undef before.)
    • Merely by using a key that had not been used before, Perl causes a new hash-bucket ($$foo{'bar'} or if you prefer $foo->{'bar'}) to appear.
    • Using the bucket as an array @{...} causes it to be an array, initially empty, to which we in this example push the arbitrary value 3.
    Perl has, in short, followed its usual practice of “do what I mean.”

    You could, therefore, simply loop through the set of keyword=value pairs, and push a value into a bucket for that keyword, trusting auto-vivification to automagically make those elements properly for you.   (Perhaps you also use:   next unless defined($value); ... in that loop.)   Welcome to “The Swiss Army® Knife of Data Processing.”

    If duplicates are a possibility and considered to be a problem, auto-vivification can be used just as easily to make a hash of hashes, e.g.
    $$foo{$keyword}{$value} = 1;
    or something similar.   In any case, Perl allows you to achieve the desired results with a paucity of code.

      Hej Sundialsvc4 and thanks for your reply,

      I'm not really sure if I understood everything you wrote, but I think I might understood your idea.

      But how to assign for example key CMG12 to 12th UID in the file ?

        As you parse the file one line at a time and come to CMG1=Ja, the string CMG1 is your keyword and Ja is the associated value.   If you needed to know that it was in the twelfth position, then you could for example set up a hash-of-hashes data structure such that $hoh->{'CMG1'}{'Ja'} = 12.   Or whatever else suits your fancy.   My key point was that, with auto-vivification, you can establish such data structures very easily. You refer to an unassigned variable as a hash ... and it is a hash.   You execute as an assignment-statement what I wrote just above, and the desired hash-of-hash element simply appears.   $hoh->{'CMG1'} exists, and it has a key {'Ja'}, and that key has the value 12.   Presto.   Arrays work the same way.   It’s entirely up to you to determine what structure you want, but very easy to get it.

Re: Manipulating data structure
by Cristoforo (Deacon) on Aug 16, 2012 at 22:03 UTC
    Are these correct as shown below or did you missprint them? If they are missprints, should they be 'DOL' or 'DOLD'?

    Do the 'numbered' keys always occur at the bottom of the list?

    Chris

    UID= UID=FRLARS UID=ANJA08 FNA= FNA=Fredrik FNA=Anja ENA=Exp-pri ENA=Larsson ENA=Daun PRE=(0117) PRE=(0117) PRE=(0117) NYTT=23400 NYTT=23403 NYTT=23404 PRI1=Nej FOR1=Nej DOLD1=Nej should this be DOL? CMG1=Ja MEX1=Nej PRI2=Nej FOR2=Nej DOLD2=Nej should this be DOL? CMG2=Ja MEX2=Nej PRI3=Nej FOR3=Nej DOL3=Nej not like the 2 entries above CMG3=Ja MEX3=Nej
      Hej Cristoforo and thanks for your reply,

      You are right, it was a missprint, it is DOL1, DOL2, DOL3, etc.

      And yes, numbered keys always goes on the bottom of the list (I think it's a consequence of using radio buttons which are seen as one "part")

      One strange thing I've noticed when I moved this part out of CGI to a separate script and done a dump using Data::Dumper is that all of those numbered keys goes to a first hash ?!?

      $VAR1 = { 'FOR3' => 'Nej', 'UID' => '', 'DOL3' => 'Nej', 'DOL1' => 'Nej', 'FNA' => '', 'MEX2' => 'Nej', 'CMG1' => 'Ja', 'CMG2' => 'Ja', 'MEX1' => 'Nej', 'DOL2' => 'Nej', 'PRI3' => 'Nej', 'spara' => 'Spara', 'PRI1' => 'Nej', 'ENA' => 'Exp-pri', 'FOR1' => 'Nej', 'MEX3' => 'Nej', 'NYTT' => 23400, 'FOR2' => 'Nej', 'PRI2' => 'Nej', 'PRE' => '(117)', 'CMG3' => 'Ja' }; $VAR2 = { 'UID' => 'FRLARS', 'PRE' => '(0117)', 'ENA' => 'Larsson', 'NYTT' => 23403, 'FNA' => 'Lars', }; $VAR3 = { 'UID' => 'ANJA08', 'PRE' => '(0117)', 'ENA' => 'Daun', 'NYTT' => 23404, 'FNA' => 'Anja', };
      Anyone knows why ?

        You have to tell Dumper that the element is an array-reference.   Otherwise, it will “flatten” the list for printout and dummy up those $VARn pseudo-names within Dumper’s own output.   But it’s only for its own printing purposes:   those names do not actually exist anywhere.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://987716]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2014-07-13 07:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (248 votes), past polls