Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to create a 2d array from file input 1

Status
Not open for further replies.

Evan145

Technical User
Dec 24, 2001
33
IE
Hi,
I am new to this site and in the process of teaching myself
perl. I have a question that I hope someone can answer.
I am playing about with a small script that uses a 2D array,
I think its called an annonymous array( feel free to correct
me, if I'm wrong ). The array is 'coded' into the script but I would like to fill it from a data file.

My array is like this...........

my @picks;
@picks = (
[ 2, 6, 9, 16, 18, 28 ],
[ 2, 11, 16, 18, 28, 29 ],
[ 11, 18, 20, 21, 25, 28 ],
[ 10, 11, 13, 17, 28, 34 ]
);

the script works fine because I can do the following...

for my $p ( 0 .. $#picks ) {
my @set = @{$picks[ $p ]};
if ( grep /^$n$/, @set ) {
#dosomething;
}
}

My question is: How would I read in the elements into @picks
from a data file, without having to edit further code.

I have tried something like this, but to no avail...

$filename = "data.txt";
my @picks;

open(DAT, &quot;<$filename&quot;) or die(&quot;Could not open file!&quot;);
@picks=<DAT>;
close(DAT);

where &quot;data.txt&quot; loks like this ......

1 2 5 7 9 11
12 13 17 27 33
1 23 24 29 37 42


Please, this is not homework or the likes, I AM trying to
teach myself.

Thanks
 
Update:
I'm trying this now.......

open(DAT, &quot;<$filename&quot;) or die(&quot;Could not open file!&quot;);
@picks=split(/' '/,<DAT>);
close(DAT);

but
print @picks;
only contains the first line of the textfile.

I still need to break into a 2D array.. ...If I solve this

Thanks
Evan
 
Evan145,

I'm just a Perl hack, but I think this is what you're looking for:

Code:
my @data;
 
open( READ, &quot;< $filename&quot; ) or die 'Cannot open $filename: $!';

while (defined ($_ = <READ>)){ push @data, [split/,/]; }

close( READ );

The
Code:
&quot;[split/,/]&quot;
does the work of splitting your file data into a 2d array and &quot;while (defined ($_ = <READ>))&quot; processes the file into @data one line at a time for you until it hits the end of the file. Each element of @data can then be accessed by referencing &quot;$data[$row][$col]&quot;.
'Well, it's one louder, isn't it?...
What we do is, if we need that extra push over the cliff, you know what we do?...Eleven. Exactly. One louder.'
 
You are close. Using split is the right idea. Learning perl's data structures isn't the easiest thing in the world, but once you get the basics - you be able to do really cool things. Arranging data logically in multidimensional data structures, and knowing how to interact with that data, makes programming some complex tasks almost trivial.

What you created with your first code:
Code:
@picks = (
                  [  2,  6,  9, 16, 18, 28 ],
                  [  2, 11, 16, 18, 28, 29 ],
                  [ 11, 18, 20, 21, 25, 28 ],
                  [ 10, 11, 13, 17, 28, 34 ]
                 );
Is an Array of anonymous array references. Usually just referred to as an Array of Arrays. Or, as you had it, 2D array.

Just for learnings sake, the following code produces the same results:
Code:
{
my @array_of_nums = ( 2,  6,  9, 16, 18, 28 );
my @more_nums = ( 2, 11, 16, 18, 28, 29 );
my $array_ref = [ 11, 18, 20, 21, 25, 28 ];

@picks = (
    [ @array_of_nums ],       # anon array with that is a 
                              # copy of @array_of_nums

    \@more_nums,              # reference to @more_nums,
                              # change this, and you're
                              # changing @more_nums

    $array_ref,               # regular array ref here

    [ qw/10 11 13 17 28 34/ ] # I love the qw// operator.
    );
}

Anyways, here is one way that you could create the desired structure from the datafile you described:
Code:
open(DAT, $filename) or die &quot;Could not open file: $!&quot;;

while(<DAT>){ # reads each line into $_
  push @picks, [ split(/ /, $_) ];
  }

close DAT;

But a more beginner friendly way, might be:
Code:
open(DAT, $filename) or die &quot;Could not open file: $!&quot;;

while(<DAT>){
  my @values = split(/ /, $_);  # array of values is created

  push @picks, \@values;        # push a reference to the
                                # @values array, onto the
                                # tail of the @picks array.
  }

close DAT;

Hope this helps.

--jim

* * * Merry Christmas and Happy New Year! * * *

( Don't touch that Red Flag link you crazy freak, it's just a holiday greeting! )
 
BTW - I didn't see mlg4035's post when I began typing, so my post is just a response to Evan's. Don't want there to be any confusion...

--jim * * * Merry Christmas and Happy New Year! * * *

( Don't touch that Red Flag link you crazy freak, it's just a holiday greeting! )
 
Brilliant guys, the reponse time alone has me amazed.

Thanks for yer help,

Merry Christmas
 
Evan145, Codiferous,

Thank you for your post Codiferous, I was only grasping at straws anyway. Seems like I'm doing a lot of that these days, maybe you guys can help me with another problem:

I'm currently strugging with trying to get my head around
exactly what you referred to:

&quot;Arranging data logically in multidimensional data structures, and knowing how to interact with that data,...&quot;

I'm having the hardest time breaking down a CSV data file into chunks based on the first field of data: all lines with the same first value need to be grouped together so I can print them out into neat HTML tables. (The first field is the table name.) I want to then create HTML files based on the first letter of the tables, ie. all table names that start with 'A' would be on one page, 'B's on another, etc...

Do you (or anyone else out there) have any suggestions about how to approach this task? Many thanks in advance.
'Well, it's one louder, isn't it?...
What we do is, if we need that extra push over the cliff, you know what we do?...Eleven. Exactly. One louder.'
 
You know, there was another guy with a similar problem not too long ago, and he was building a nice &quot;home builders&quot; web site. It sounds like your data presentation needs are similar, as are the logical relationships between the data you have.

You would like to take each line of the data file, place them into groups based on the first value of the line, and then display the data per key. Depending on how large the file is, there are different ways to go about it. But, since you only plan on displaying ONE set of groups at one time (&quot;ie. all table names that start with 'A' would be on one page, 'B's on another, etc...&quot;), I would recommend the following: (Code is untested)
Code:
$letter_U_want = 'B';

open(FILE, &quot;/path/to/sample_data_file&quot;);
my $category;
my @line;
while(<FILE>){
  if(/^$letter_U_want/){   # Make sure this is an entry
                           # we care to display.
    @line = split(/,/ => $_);
    $category = shift @line;  #  Gets the Group name
                                 #  off of the array.

    push @{$hash_of_arrays_of_arrays{$category}}, [ @line ];
    }
  }

# Now we have our datastructure, you can do whatever 
# you want.  Like display it:

for (sort keys %hash_of_arrays_of_arrays){
  print &quot;KEY: $_\n&quot;;
  for $AoA_ref(@{$hash_of_arrays_of_arrays{$key}}){
    for $arr_ref(@{$AoA_ref}){
      print &quot;@{$arr_ref}\n&quot;;
      }
    }
  }

# Sample_Data_File
# Baseball, 1, 2, 3, 4
# Baseball, 3, 4, 23, 12
# Football, 4, 5, 6, 7
# Basketball, 9, 2, 4, 6
# Basketball, 4, 5, 4, 6
# Basketball, 3, 2, 3, 3
# Basketball, 4, 7, 4, 6

This would output the Baseball, and then Basketball data - if I coded right.
I hope this helps.

--jim * * * Merry Christmas and Happy New Year! * * *

( Don't touch that Red Flag link you crazy freak, it's just a holiday greeting! )
 
Thanks again Coderifous,

However the only way I can get anything to print is to use:

Code:
  for $category(keys %hash_of_arrays_of_arrays ) {
        print WRITE &quot;$category: @{$hash_of_arrays_of_arrays{$category}}\n&quot;;
   }

And I either get &quot;B: ARRAY(0x1b1a364) ARRAY(0x1c4c358) ARRAY(0x1c4c388) ARRAY(0x1c488bc) ARRAY(0x1c488ec) ARRAY(0x1c4891c) ARRAY(0x1c4894c) ARRAY(0x1c4897c) ARRAY(0x1c489ac) ARRAY(0x1c489dc)&quot;,
or,

&quot;10&quot;,

depending on whether I leave &quot;@{$hash_of_arrays_of_arrays{$category}}&quot; between quotes or outside of quotes...Any ideas? 'Well, it's one louder, isn't it?...
What we do is, if we need that extra push over the cliff, you know what we do?...Eleven. Exactly. One louder.'
 
Code:
for $category(keys %hash_of_arrays_of_arrays ) {
  print WRITE &quot;$category: &quot;;
  for $array_ref(@{$hash_of_arrays_of_arrays{$category}}){
     print &quot;@{$array_ref}\n&quot;;
     }
   }

Does that work?

--jim * * * Merry Christmas and Happy New Year! * * *

( Don't touch that Red Flag link you crazy freak, it's just a holiday greeting! )
 
Thanks again Coderifous,

It works beautifully! Merry Christmas! 'Well, it's one louder, isn't it?...
What we do is, if we need that extra push over the cliff, you know what we do?...Eleven. Exactly. One louder.'
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top