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

I need to create a separate associative array for each column of data that I have. However, the number of columns varies. I wish to name these arrays systematically, %x1, %x2 %x3 etc. I wish to use a for loop to go through each of these in order and process them. How can I write the name of the variable %x# where # represents is the counter for the loop? (I know about for loops already and am writing a script). Thanks in advance for any help, Duncan
  • Comment on naming a variable with the datum from another variable

Replies are listed 'Best First'.
Re: naming a variable with the datum from another variable
by Corion (Patriarch) on Feb 12, 2005 at 17:06 UTC

    There are two red flags here:

    1. Variable names that end in numbers - it is wrong almost every time when you have a variable name that ends in a number. Replace such variables by a single array.
    2. Using a variable as the name of a variable - TheDominus has said it much better than I ever will. In short, it just is a bad idea to do this. Replace the variable that you want to point to by a hash or an array.

    Of course, it still is possible in Perl do use a variable to access a second variable by name, this is called a "soft reference", but unless you can tell us more about why you can't use an array or a hash as a solution instead, it is better for you to first learn about how to do that.

Re: naming a variable with the datum from another variable
by Anonymous Monk on Feb 12, 2005 at 17:06 UTC
Re: naming a variable with the datum from another variable
by duncharris (Initiate) on Feb 12, 2005 at 17:19 UTC

    I have a working version of this that works for two columns, I need to make it work for more.

    It's a script for normalising array data so that the data from each column have the same distribution.

    I have tab delineated data that need to be read in, e.g. for two columns

    ID_REF IDENTIFIER GSM29783 GSM29784 31307_at L17325 77 788 31308_at L17330 -777 -877 31309_r_at U50277 7 8 31310_at X52009 -7777 -887 31311_at X61070 77777 88

    I then sort each column individually by value (done)

    I then have to average both of the top values, then both of the 2nd top values etc.

    I then have to output those back into the original order they came from.

    I'll give you the working code if you like?

      Okay, so that's bad way of doing it, but how do you do it because I have a working program that I just need to add a couple of loops into, and fiddling around with the data structures at this stage could be messy.

      However, I would like to learn how to do it properly. I'm using an associative array already so that I can number the columns. Can I put an associative array within another associative array without all the data in them getting jumbled up?

        Can I put an associative array within another associative array without all the data in them getting jumbled up?
        Yes. That is a Hash of Hashes, HoH in short. see perlref and perlreftut. In fact you can create any kind of data-structure using perl-hashes and arrays. I donīt know if there is a "deepness"-limit but i doubt that.

        #sample set up a hash of hashes my %h = ( key1 => { subkey11 => subval11, subkey21 => subval21 }, key2 => { subkey12 => subval12, subkey22 => subval22 }, ); #access it print $h{key1}->{subkey11}; #loop it for ( keys %{$hash->{key2}} ) { print $hash->{key2}->{$_}; }
        Update:
        And yes, show us your code. But be sure to strip all non-relevant parts.

        holli, /regexed monk/

        I'm not entirely sure what you're trying to do - although here's a guess. It's not using hashes (associative arrays), but it could.

        use Data::Dumper; my $header = <DATA>; my @cols_h = split /\t/, $header; my @data; while (<DATA>) { chomp; my @info = split /\t/; push @data, \@info; } # uncomment this to see the data we have so far. #print Dumper(\@data); foreach (@data) { my $avg = ($_->[2] + $_->[3]) / 2; push @$_, $avg } # uncomment this to see the data we have so far. #print Dumper(\@data); # at this point, each @data is an array of arrays. # Each of the arrays contained in @data is "anonymous" (unnamed). # These anonymous arrays have the four columns (0-3), and a fifth colu +mn # which is an average of columns 2 and 3 (zero-based). __DATA__ ID_REF IDENTIFIER GSM29783 GSM29784 31307_at L17325 77 788 31308_at L17330 -777 -877 31309_r_at U50277 7 8 31310_at X52009 -7777 -887 31311_at X61070 77777 88