tags:

views:

677

answers:

2

Heylo again,

I've been trying to make my program somewhat easier to maintain. I have an array which I declare:

my @pizza = ($p1 = "Pizza One", $p2 = "Pizza Two" );

I then go ahead and put this @Pizza array in another array, like so:

my @food = (\@pizza);

When I attempt to access either $p1 or $p2 via the @food property I get a value returned like "Array{0x8001}" which appears to be a memory reference. What i tried was this:

$test = ${$food[$pizza[$p1]]};

What is the corret way to access this? I am looking to NOT use indexes in order to ease program readability. could you guys point me in the right direction?

Regards,


This is what I am trying to do:

I have several databases (for talks sake this is an example)

Database One
Table One (D1T1) | Column One | Column Two | Column Three | Column Four
Table Two (D1T2) | Column One | Column Two | Column Three

Database Two
Table One (D2T1) | Column One | Column Two| Column Three
Table Two (D2T2) | Column One | Column Two| Column Three
Table Three (D2T2) | Column One | Column Two| Column Three

Between these two databases there is information that is relative to particular records right across them both. What I am trying to do is create an array (each array will represent a database) and insert variables (each variable will represent a table.field. within the datasource) Once I have done this I am creating an array to hold all teh arrays (The ones that represent the db's) as this array will represent a single entry right across the two databases which I can then act on. Example:

@D1 = ( t1.col1, t1.col4, t2.col1 ); @D2 = ( t1.col1, t2.col1, t3.col2, t3.col3);

@rec = ( \@D1, \@D2 );

If I want to know what was held in Database 2 -> Table 2 -> Column 4 what would the statement be? Should I be using hashes instead? I do have a requirement for this two dimensional array/hash.

Any help is much appreciated.

MC

+10  A: 

Not knowing what you're trying to accomplish, what data you're modeling, all I can help you with is the syntax confusion. There's confusion here on several points.

# You wrote
my @pizza = ($p1 = "Pizza One", $p2 = "Pizza Two" );

That does not do what you mean. It makes the array ("Pizza One", "Pizza Two") but it also sets $p1 to be Pizza One and $p2 to be Pizza Two. I think you're trying to assign Pizza One to the key p1. I think you want to use a hash/associated array:

# Try a hash
my %pizzas = (p1 => "Pizza One", p2 => "Pizza Two");

Now $pizzas{p1} is Pizza One. Alternatively, just make a list:

# An array
my @pizzas = ("Pizza One", "Pizza Two");

And then $pizzas[0] is Pizza One. Moving on...

# You wrote
my @food = (\@pizza);

You're trying to make another list refer to @pizza. The above makes $food[0] reference to @pizza which is not what you meant. References in Perl are scalars and have different syntax.

# What you probably meant
my $food = \@pizza;

Now $food->[0] is Pizza One and $food->[0] is Pizza Two.

# You wrote
$test = ${$food[$pizza[$p1]]};

Smacks of just adding more braces until you got output. I'd recommend reading the Perl Data Structures Cookbook. Oh, and turn on warnings. Don't turn them off until they all go away and don't turn them off because there's too many of them. Really. Really really.

Update

"I want to know what was held in Database 2 -> Table 2 -> Column 4 what would the statement be?"

Don't use numbers. Name them, because I'm sure they have names. So yes, you want hashes. So let's say Database Foo -> Table Bar -> Column Baz. You'd access that like...

$values = $databases->{Foo}{Bar}{Baz};

or long hand

$tables  = $databases->{Foo};
$columns = $tables->{Bar};
$values  = $columns->{Baz};

Where $values can be an array ref of all the values of Foo.Bar.Baz, or another hash keyed by the primary key of Foo.Bar. Which makes more sense depends on what you're doing to do with the data.

I'll leave it to you to adapt Chaz's answer to generate hashes instead of arrays.

Of course, I must ask why dump the whole of both databases out into a big in-memory structure and then work on it? If you have databases, query them. It'll be faster and more flexible.

We're back to that most basic of questions; what is it you're REALLY trying to do?

Schwern
I think he means he doesn't want a lot of magic numbers sprinkled through his code (like $object[1]), for which the solution is either a hashref instead of an arrayref, or "use constant" or "use enum" to declare constants for your field indexes.
cjm
That is exactly is cjm. The keys I will access need to represent the data they hold. I have edited the original post to clarify what it is I am trying to do.I think hash references are the way to go, I'm googling up two dimensional hashes to see if I get anywhere. I really appreciate you help.
Ahh, I misparsed it as "I am NOT looking to use indexes..."
Schwern
Hi Schwern, thanks for the answer.What I am trying to do is collect (relative) information across a wide range of databases, and once I've collected that information I will begin performing checks on this information that will trigger an activity based on that information. I will sometimes need to perform checks of D1T2C1 (Database One, Table Two, column One) to make sure the value of its relative record D2T1C1 (Database Two, Table One, Column One) has a particular value.Please note that I don't hold the entire db in memory, I flush the memory on each record iteration and recheck.
A: 

Based on what you described is sounds like you need something like this:

#!/usr/bin/perl

use strict;
use warnings;

my @dbs;
while (<DATA>) {
    chomp;
    if (/^Database/) {
        push @dbs, [];
        next;
    }
    my @table = split /\s*\|\s*/;
    push @{$dbs[-1]}, [ @table[1 .. $#table] ];
}

print "datbase 1, table 2, column 1: $dbs[0][1][0]\n";

for my $db (0 .. $#dbs) {
    for my $table (0 .. $#{$dbs[$db]}) {
        for my $col (0 .. $#{$dbs[$db][$table]}) {
            print "($db,  $table, $col) is $dbs[$db][$table][$col]\n";
        }
    }
}


__DATA__
Database One
Table One (D1T1) | D1T1C1 | D1T1C2 | D1T1C3 | D1T1C4
Table Two (D1T2) | D1T2C1 | D1T2C2 | D1T2C3

Database Two
Table One (D2T1)   | D2T1C1 | D2T1C2 | D2T1C3
Table Two (D2T2)   | D2T2C1 | D2T2C2 | D2T2C3
Table Three (D2T2) | D2T3C1 | D2T3C2 | D2T3C3
Chas. Owens