The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

import-bot (20211) [Avatar] Offline
#1
[Originally posted by daniel]

I have a two-element array. The first element is a unique element called
instrument_num. The second element is a non-unique number called book_page.
The problem is I have to look up the value based on the non-unique value
book_page, so I can't create a hash keyed on book_page. I see on pg 44
something close, but I don't know how to make it fit.
The code I have is working is real slow, does anyone know of a
better way?

Current code:
# GET every match from MASTER record [instrument_num][book_page]
my $j;
my @found_in_master=();
my $howmany_mas=0;
for ($j=0;$j<@master_array;$j++) {
if ($master_array[$j][1] eq $book_page ) {
push @found_in_master,$master_array[$j][0];
}
}
$howmany_mas=@found_in_master;
print "I found $howmany_mas matches
";
import-bot (20211) [Avatar] Offline
#2
Re: finding all elements in a 2D array
[Originally posted by dave]

If you're doing a lot of this, then it's certainly worth building a reverse
lookup hash. As you say, the fact that you don't have unique values is a
problem, but you can get round that like this (I'm guessing at your original
data structure):

my @data = ([1, 'page'], [2, 'another page'], [3, 'page'], [4, 'another page']);

my (%lookup, %rev_lookup);

foreach (@data) {
# standard lookup array
$lookup{$_->[0]} = $_->[1];

# reverse lookup
push @{$rev_lookup{$_->[1]}}, $_->[0];
}

You can now easily check for the existance of pages in both directions.

hth,

Dave...
import-bot (20211) [Avatar] Offline
#3
Re: finding all elements in a 2D array
[Originally posted by daniel]

I am doing a lot of this, this one routine consumes 95% of the processing
time(according to -dsmilieProf). The way it was written, the code will take
several DAYS to complete - with thunderstorms scheduled for the next several
days (ie:power outages) here in Virginia, US, I am very motivated to improve.
As a newbie to references, I am still struggling with the English translation
from the Perl.
After re-reading Appendix B.6 "essential perl" regarding references, some
sunlight got through the fog in my brain.
I am OK with the first part, building the standard lookup[although I thought
it was a hash, not array like commented]. Anyway, I am confused on the
reverse lookup hash(or array, especially how to use it. Every time I put in a
print statement trying to look at the value, it gives me an error.
I was begging for a continuation of the "You can now easily check for the
existance of pages in both directions". by doing ....
Further insight would be greatly appreciated.
thanks, Daniel
import-bot (20211) [Avatar] Offline
#4
Re: finding all elements in a 2D array
[Originally posted by trelane]

> If you're doing a lot of this, then it's certainly worth building a reverse
> lookup hash. As you say, the fact that you don't have unique values is a
> problem, but you can get round that like this (I'm guessing at your original
> data structure):

Since daniel was still having problems with this let me rewrite
your example with even more comments Dave.

# this is the data structure. It's a list that contains
# lots of other lists. It does this by using the anonymous
# list syntax so that @data actually contains a list of references
# to other lists that conain the data.

my @data = ([1, 'page'], [2, 'another page'], [3, 'page'], [4, 'another page']);

# declare the name of the hashes we are going to use

my (%lookup, %rev_lookup);

# for each of the elements in @data, i.e. for each of the mini-lists
# that are referenced in this list...

foreach (@data) {

# a reference to the list we are currently dealing with is now
# stored in $_. To get at the first value we need only write
# $_->[0]. To get at the second value we can write $_->[1].

# Create the lookup hash. To do this we need to get the first
# element of the array, and use it as a key for the second element
# of the array

$lookup{$_->[0]} = $_->[1];

# reverse lookup hash. Each page name in this will
# be the key for a list ref that points to a list of
# all the pages numbers that have this title.

# To do this we get the list
# ref out of the hash by doing $rev_lookup{} with the
# name of the page ($_->[1]), and push $_->[0] (the
# page number) onto the end of the list that the list
# ref points at

push @{$rev_lookup{$_->[1]}}, $_->[0];
}


Okay now let's look at some useage example

# print the title of page 3
print $lookup{3} . "
";

# print the first page to have the title 'another page'
print $rev_lookup{"another_page"}->[0];

# print the second page to have the title 'another page'
print $rev_lookup{"another_page"}->[1];

# print out a list of all the page numbers that have the
# title "another_page"
print join ",",@{ $rev_lookup{"another_page"} };


Finally I suggest using a small data set and then printing out
the whole thing using Data:smilieumper to get a better understanding
of what's going on

use Data:smilieumper;
print \%lookup;
print \%rev_lookup;
import-bot (20211) [Avatar] Offline
#5
Re: finding all elements in a 2D array
[Originally posted by daniel]

Mark,
That was exactly what I was hoping for - an english translation of the perl
with examples of usage.

Many thanks for shedding some light on 2D arrays. It is opening up a whole
new world to me.

Thanks again for the post.
Daniel