On Jun 24, 2005, at 5:07, Anthony Roe wrote:

A = Reads URI from URIHASH.
Visits site A.
Parses all URIS on site A and for each URI found adds the URI to the URIHASH.

A = Reads next URI from URIHASH.
Visits site A.

And so on... until the MAX URIHASH size is reached.

My question is, is there any way to iterate through a hash in this manner.

I tried foreach():

foreach $key (keys %URIHASH){}

You don't see the changes because

    keys %URIHASH

returns the list of keys *once*, when the foreach is entered. That list is kept in memory, it is not recomputed in each iteration. So you are modifying %URIHASH just fine, but iterating over the old list of keys.

and this does not work. What occurs is the entry that exists in the
URIHASH when the foreach loop is entered, is processed.
any additional entries that are added during the loop are not processed.

I also tried each():

When a program iterates over a hash it can't modify it. That's the idea.

That happens in general to collections no matter the programming language because of their underlying implementations and the ones for iterators. One needs to check the documentation about it to see what's allowed in each case.

When you are iterating in Perl over a hash with each(), the only valid modification (and so an exception to the rule stated above) is a case of delete. From perldoc -f each:

    If you add or delete elements of a hash while you're
    iterating over it, you may get entries skipped or duplicated,
    so don't.  Exception: It is always safe to delete the item most
    recently returned by "each()", which means that the following
    code will work:

        while (($key, $value) = each %hash) {
            print $key, "\n";
            delete $hash{$key};   # This is safe
        }

A solution for your program is to maintain some sort of auxiliar hash or array, sometimes it makes sense to merge it with the hash after each iteration, sometimes not, depending on the program. For instance, something like this:

    my @uris = keys %URIHASH;
    while (@uris) {                          # checks size, no problem
        my $uri = shift @uris;               # short @uris by one
        push @uris, @newuris;                # add uris to the array
        @[EMAIL PROTECTED] = (1) x @newuris; # merge them in the hash
    }

That's an example, but anyway you see why this happens and what needs to be fixed.

-- fxn

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to