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

Kind of a continuation question off my earlier post but it need not be read to understand this question.

I have two arrays. @texts and @images. Both contain information FOR each other. $texts[0] relates with $images[0].

This data is being used with WWW::Mechanize to fill in a form so I can collect results. The problem is, sometimes @texts can have more than one identical item in it and it wouldn't make sense to fill out the form any more than I have to since the results would be the same.

I have to loop over @texts to get the results 5 times so it looks like.

UPDATE: %texts is @texts but it removes the duplicates and has a numeric value for the qty of times that key was in there. @images isn't in this snippet but it's there, it just sits there holding one string of data that doesn't change throughout the script.

################## foreach (keys %texts) { my $key = $_; $mech->get($url3); for (1 .. 5) { $mech->submit_form( form_number => 3, fields => { shopwizard => "$key", criteria => 'exact' } ); #print $mech->content; } }
The question is, how can I keep the related information together while knowing NOT to search an already searched-for $text? I was thinking a hash would be the only way to store the results since each element would get 5 separate return values (1 for each page load).

I am TOTALLY lost on how to use my stored information and use it to search just unique items while keeping all the information together.

Replies are listed 'Best First'.
Re: Keeping separate array data related
by davido (Cardinal) on Oct 05, 2005 at 00:46 UTC

    If I understand your question, maybe you should use a hash of arrays.

    use Data::Dumper; my %data; foreach my $index ( 0 .. $#texts ) { push @{$data{ $images[ $index ] }}, $texts[ $index ]; } print Dumper \%data;

    Now you've got a hash where the keys are the various images, and the values are one or more texts, held in anonymous arrays. Dumper will show you what you've got here. If you still need to preserve order, keep the original images array around as the sorted list of keys.


    Dave

Re: Keeping separate array data related
by muba (Priest) on Oct 05, 2005 at 00:50 UTC
    foreach (keys %texts)
    You kinda lost me here. You speak about arrays but keys and %texts are clearly (update: related to) hashes to me. What exactly do you want?

    As for your question, use a hash indeed. I suppose that when a text entry occurs twice, the same image occurs twice as well?

    $texts_and_images{"$text"} = $image; # set text and image @all_texts = keys %texts_and_images; # have a list of all texts @all_images = values %texts_and_images; # have a list of all images $image = $texts_and_images{"$text"); # have the associated image of + a text
    HTH
Re: Keeping separate array data related
by graff (Chancellor) on Oct 05, 2005 at 01:18 UTC
    I'm afraid I'm a bit confused too, in part because I don't see any relation between the code you showed and the issues you describe.

    In terms of handling two related arrays, keeping the indexing in sync while being able to skip an iteration when you've seen an array value previously, you could keep everything as-is and add a hash for "seen" values inside the loop:

    my %seen = (); for my $i ( 0..$#texts[0] ) { next if ( $seen{$texts[$i] ); $seen{$texts[$i] = 1; ... # do stuff with $texts[$i] and $images[$i] }
    But if this loop over the arrays is itself being repeated five times (if I understand you right), then it may be better to structure the data as a hash in the first place, instead of two arrays.

    Since the value of @texts appears to work for you as the "key" (you don't want/need to handle a given "text" value more than once), then why not just make this the hash key, and make the value of @images the hash value:

    my %text_image; @text_image{@texts} = @images; for my $text ( keys %text_image ) { my $image = $text_image{$text}; # do stuff with $text and $image... }

    This assumes that each time you see a given value from @text you should likewise see a repeated value in @image at that index. If a single value of @texts occurs more than once but with different corresponding values of @images, then why do you want to skip repeat occurrences of "text" values? (The above code will only retain the last such pairing, but there are easy ways to fill the hash working from the ends of the arrays to the beginnings.)

    Anyway, with that hash approach, the elements of the two arrays remain linked to each other, and it shouldn't matter in what order the hash keys are handed to a for loop over the keys.

    (Then again, if for some reason you need the loop to treat the entries in the same specific order as the original arrays, you can build an array of arrays, and use a "%seen" hash when doing that, so as to load only unique values from @text.)

Re: Keeping separate array data related
by TheEnigma (Pilgrim) on Oct 05, 2005 at 01:15 UTC
    I also am confused. But limiting my comments to your question of not using duplicate entries from the array @texts, you could do the following:

    Add this before a loop that iterates over the array:
    %seen = ();

    Add an unless after your submit_form call. $item is the current item from @texts.
    mech->submit_form( .... ) unless $seen{$item}++;

    TheEnigma

Re: Keeping separate array data related
by GrandFather (Saint) on Oct 05, 2005 at 00:50 UTC

    I'm confused too. Your description talks abour "@texts and @images", but they don't appear anywhere in your sample code.

    In general if you have paired items use a single array or hash (as appropriate) containing references to lists containing the paired data. Something like this:

    my @pairs = (["image 1 text", \$image1], ["image 2 text", \$image2], . +..);

    Perl is Huffman encoded by design.