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 wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

searching array of arrays... 2

Status
Not open for further replies.

ailse

Programmer
Jan 20, 2004
79
GB
this is related to my previous question, getting pretty stuck with my next problem!

i have an array of arrays:

i have manged to read the data into an array of arrays, i did end up using regexp in the end:

Code:
@records = <DATA>;

foreach $record (@records) {
    if ($record =~ /\s*(\S+)\s(.+) > (.+) ; (.+)/) {
        $id1 = $1;
        $id2 = $2;
        $id3 = $3;
        $id4 = $4;
        @temp = ($1, $2, $3, $4);
        push @AoA, [ @temp ];
    }
}

my next problem is that I need to search this array of arrays - I know how to search a regular array, but in this case I need to search the first element and match the number part of it, i.e. each record looks like this:

[code
["ID1:HUF000G" "some text here" "ID2" "ID3"]
[/code]

and I need to match the first field so if i am searching for "HUF000G" the whole of that array is returned... any hints? been searching everywhere for some syntax, but couldn't find anything relevent... also, i appreciate this would be easier if i used a hash, but that's no possible as there is no unique identifier for each record i.e. there is more than one array in the array or arrays that contains HUF000G and I need to return all of them,

thanks :)
 
Here's one way to search the first element of each array.

Code:
foreach (@AoA) {
    if (${$_}[0] =~ /regex/) {
        # Match found
    }
}
 
The filtering function I would use is [tt]grep[/tt]. It takes a code block and an array, and return a new array with all elements for which the code block evaluated to true. The code block is the same as the one inside the [tt]if[/tt] of rharsh exemple.
Code:
my @matching_arrays = grep { ${$_}[0] =~ /$regexp/ } @AoA;
Here @matching_arrays will only contain the arrays of @AoA whose first element matched $regexp.

You could use it like this:
Code:
# Loop on all elements matching regexp
foreach (grep { ${$_}[0] =~ /$regexp/ } @AoA) {
    # ...
}

I think this is a more 'natural' (for perl :) ) way to do it : you do not "loop on all array elements and work only on matching elements" but you really "loop on all matching elements". Look at the comment in the code just above: the line of code below is its direct translation in perl.

I do not know if there is an impact on performance, though.

--------------------

Denis
 
You're right Denis, I thought about rewriting it with grep as I hit submit. Too late! :) Grep is the way to go.
 
cheers for the tips guys - I have used it the following way:

Code:
my @matching_arrays = grep { ${$_}[0] =~ /$results_array/ } @AoA;

this doesn't seem to work - can i use the variable $results_array in that way in the regexp? basically I have an array of numbers stored already (@results_array), and for each one in this results_array i'm searching the first element of all the arrays in the @AoA and returning all arrays that match. sorry to keep asking these questions but I really appreciate the help so far!

cheers :)

 
You just add a loop on elements of @result_array.

Depending on what you want exactly:
1) If you want all matching elements for all result in @results_array in one big array:
Code:
# Create an empty array
my @matching_arrays;

# For each result in results_array
foreach my $result (@results_array) {

    # Append to @matching_arrays all elements of AoA matching $result
    push @matching_arrays, grep { ${$_}[0] =~ /$results/ } @AoA;

}

# Here work on @matching_array elements.

2) If you want matching elements for each result in @results_array in different arrays:
Code:
# for each result in @results_array
foreach my $result (@results_array) {

    # Set @matching_arrays to all elements of AoA matching $result
    my @matching_arrays = grep { ${$_}[0] =~ /$results/ } @AoA;

    # Here work on @matching_array elements.

}

Note: Some comments here are totally useless: if someone knows anything about perl, no need to add
[tt]# for each result in @results_array[/tt]
as comment to
[tt]foreach my $result (@results_array) {[/tt]
It is not a comment, it is a pleonasm ;-)

--------------------

Denis
 
thanks for that dchoulette but i think there's still something i'm still not getting - i'm trying the following code:

Code:
#!/usr/bin/perl

use strict;
use warnings;

my @results_array = ("val1, val2");
my @matching_arrays;

my @AoA = (
         [ "val1", "GO:1234", "some more text" ],
         [ "val2", "GO:5678", "some more text" ],
         [ "val3", "GO:9876", "some more text" ],
	 [ "val4", "GO:2468", "some more text" ],
);


# for each result in @results_array
foreach my $result (@results_array) {

    # Set @matching_arrays to all elements of AoA matching $result
    @matching_arrays = grep { ${$_}[0] =~ /$result/ } @AoA;

    # Here work on @matching_array elements.
	foreach (@matching_arrays) {
  	print "$_\n";
	}
}

so what i'm trying to do here is test the code with the small results array containing val1 and val2 - the desired result would therefore be the two arrays [ "val1", "GO:1234", "some more text" ] and [ "val2", "GO:5678", "some more text" ] to be stored in yet another array of arrays, which could then be printed... any more hints?

thanks again :)
 
Should this be:
Code:
my @results_array = ("val1[COLOR=red]"[/color], [COLOR=red]"[/color]val2");

Furthemore, using the code above does not result in one array of arrays containing the 2 arrays [ "val1" ...] and [ "val2" ...]. At each iteration, the value of @matching_array is overwritten so you get 2 (one at each iteration) arrays of arrays each one containing only one of the array ["val1" ...] and ["val2" ...].

To get one array of arrays with the 2 arrays use the first example I give in my previous post (the one with the push).

Here it is again with the printing
Code:
# Create an empty array
my @matching_arrays;

# for each result in @results_array 
foreach my $result (@results_array) { 
    # Append to @matching_arrays all elements of AoA matching $result
    push @matching_arrays, grep { ${$_}[0] =~ /$result/ } @AoA;
}

# Here work on @matching_array elements.
foreach (@matching_arrays) {
    print "[ \"" . join("\", \"", @$_) . "\" ]\n";
}

--------------------

Denis
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top