Link to home
Start Free TrialLog in
Avatar of derek4716
derek4716Flag for United States of America

asked on

simple array question

I can get the following to work correctly:

*********************************
$extra = (key,value,key,value)

%group = ($extra);
while(($key,$value) = each(%group)) {
     print "value:$value  key:$key.\n";
}
****************************************

it prints out:
*********************************************
value:  Key:key,value,key,value
*********************************************

I works if I set %group equal to "('key', 'value', 'key', 'value');"

but I cannot do that because the value for $extra is pulled from the following text file:

*****************************
#array|extra
1|key,value,key,value
2|key,value,key,value
*****************************

I can change how it is in the text file though if needed.
thanks.
Avatar of Tintin
Tintin

You would find it easier to have a single key/value in the text file, ie:

1|key,value
2|key,value

then you can simply do

open FILE,"file.txt" or die "Can not open file.txt $!\n";

while (<FILE>) {
  m/\d+|(\w+),(\w+)/;
  $groups{$1}=$2;
}
How about;

%extra = (key1,1,key2,2);

foreach $key (keys %extra) {
  print "Key: $key\t Val: $extra{$key}\n";
}
Avatar of derek4716

ASKER

None on those scripts do what I aksed.  I stated before the the value for %extra was being pulled from a text file and I gave an example of the textfile.  

TinTin,
   I can't limit it to just one key,value per line...some lines may have up to six pairs.

Is there even a way to do what I want?
open F,"<file";
foreach $l (<F>){
  ($d,$p)=split(/\|/,$l);
  push(@groups,split(",",$p));
}
%groups=@groups;
close F;
ahoffmann,
   I can't get your script to do anything.?
very rude code, but should work (still taking perl-101) :)

-- infile.txt
#array|extra
1|key1,value1,key2,value2
2|key3,value3,key4,value4
3|key5,value5
4|key6,value6,key7,value7,key8,value8,key9,value9
--

-- test.pl
#!c:/perl/bin/perl

open(IN,"infile.txt");

while(<IN>) {
  chop;
  next if (/^\#/);      # skip if found comment
  my ($a,$b)=split(/\|/);
  @tmparr=split(/\,/,$b);
  foreach (@tmparr) {
#    print "$_\n";
    push (@tmparr2,$_);
  }
#  print "== $b\n";
}
close(IN);

while (<@tmparr2>) {
  $key=shift(@tmparr2);
  $val=shift(@tmparr2);
  $extra{$key}=$val if ($val);
#  print "KEY $key VAL $val\n";
}
--

I had to edit your code a little to get it to work, here is what I did, I have only one problem left:
******************************
open(IN,"infile.txt");

while(<IN>) {
 chop;
 my ($a,$b)=split(/\|/);
 @tmparr=split(/\,/,$b);
 foreach (@tmparr) {
   push (@tmparr2,$_);
 }
}
close(IN);

while (<@tmparr2>) {
  $key=shift(@tmparr2);
  $val=shift(@tmparr2);
  $extra{$key}=$val if ($val);
  print "KEY $key VAL $val\n";
}
**************************************

When it prints out the the page it prints the following(using just row 1 of the file for testing):
****
KEY key1 VAL value1 KEY key2 VAL value2 KEY VAL KEY VA
****

As you can see it prints out a couple extra KEY and VAL's.

Any ideas why?
Thanks so far, though:)
derek4716.

First you said "I can change how it is in the text file though if needed."

then you said "I can't limit it to just one key,value per line...some lines may have up to six pairs."

which statement is correct?

Also you said ahoffman's script to do anything.  What do you mean?  It works perfectly for me.  I assume you added a print to it to see the output?
my script works perfect formewith your example
what exactly is the problem?
just through in some print commands ...
also keep in mind that my suggestion work with any number of key value pairs per line,
as long as there is a even, not odd, number of key-value pairs
TinTin what I meant was that I can change how the pair are in the text file, for example, I can replace the comma's with anything needed or use quotes if need be.

ahoffmann
I will retry your script, I was probably doing something wrong.
ahoffmann, Here is the code that I tried with yours, mabye you can see what I am doing wrong.
*****************************
open F,"<test.dat";
foreach $l (<F>){
 ($d,$p)=split(/\|/,$l);
 push(@groups,split(",",$p));
}
%groups=@groups;
close F;
while(($key,$value) = each(%group)) {
     print "KEY: $key VAL $value.\n";
}
****************************
ASKER CERTIFIED SOLUTION
Avatar of ahoffmann
ahoffmann
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks, figures I did something stupid :)
one more quick question:

what if in my file I added another column such as:

******
#Id|array|extra
1234|1|key,value,key,value
3241|2|key,value,key,value
******

How do have the code go to the third column now?
And the typo of 'groups' is a classic example of where

use strict;

and

use warnings;

would have come to the rescue.
100 points to whoever can answer this question i asked earlier

**************
one more quick question:

what if in my file I added another column such as:

******
#Id|array|extra
1234|1|key,value,key,value
3241|2|key,value,key,value
******

How do have the code go to the third column now?
*******************
#!/usr/bin/perl
use strict;

open F,"test.dat" or die "Can not open test.dat $!\n";

my @groups;

while (<F>) {
  my ($data) = m/\d+\|\d+\|(.*)/;
  push(@groups,split(",",$data));
}

close F;

my %groups=@groups;

while (my ($key,$value) = each(%groups)) {
    print "KEY: $key VAL $value.\n";
}
Thanks TinTin, I created a topic for your points.  How do I continue to add additional columns?  what if I were to add 2 or 3 more cloumns, how would I let your code know?
Thinking about it, the regex can be simplified and will handle any number of columns by doing

my ($data) = m/.*\|(.*)/;

ie:  match everything after the last |
lost the focus, sorry ...
but is there something to be done for the initial question?
ahoffmann (<-- got ur name right!)

- grab some coffee :)