aaron.schweitzer has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,
I came across this below piece of code during my search for finding missing elements from a list of numbers.
However I find it a little hard to understand and would like some help in understanding this piece of code.
I found this code in a thread in this site Finding missing numbers in a list.

@idslist; ##contains a list of id numbers print "Total element in idslist = $#idslist\n"; push @missing_ids, $idslist[ $_ ] +1 .. $idslist[ $_+1 ] -1 for 0 .. $ +#idslist-1; print "Total element in missing_ids_list = $#missing_ids\n";

The most puzzling thing when i executed this code was below

Total element in idslist = 8436
Total element in missing_ids_list = 77502867

I was expecting missing_ids_list to have less elements than idslist since the loop goes only through this number.

Replies are listed 'Best First'.
Re: Understanding this code
by hippo (Archbishop) on Sep 28, 2015 at 08:44 UTC
    I was expecting missing_ids_list to have less elements than idslist since the loop goes only through this number.

    I think you may have missed the original premise in the thread which you referenced which was:

    Given an arbitrarily long list of numbers that SHOULD be consecutive, is there a simple method of finding any missing numbers?

    So, given a list like

    my @idslist = (100,200,300);

    you can see that the number of missing IDs exceeds the number in @idslist.

    The code snippet you have quoted (from here?) works by pushing ascending lists of the values between consecutive items of @idslist onto the missing list. If the values in @idslist are not consecutive (or not ascending) then nothing is pushed. Hope that explains it for you.

      Thanks
      I did sort the list and got the expected result.
      Also thanks for the explanation on the logic. Much appreciated

      Total element in idslist = 8436 Total element in missing_ids_list = 61566
Re: Understanding this code
by Ea (Chaplain) on Sep 28, 2015 at 09:24 UTC
    Small problem with this line
    print "Total element in idslist = $#idslist\n";
    Your array index starts at 0 (unless you've set $[ = 1. You haven't, have you?) and $#idslist points to the last index of @idslist, so you haven't counted the first element. I prefer to evaluate @idslist in scalar context to get the total number, so I would write
    print "Total element in idslist = ", scalar @idslist, "\n";
    or something similar.

    Sometimes I can think of 6 impossible LDAP attributes before breakfast.

    http://ldapcon.org/2015 is just an excuse to enjoy November in sunny Edinburgh

      or something similar

      double your productivity like homer, type int instead

Re: Understanding this code
by Discipulus (Canon) on Sep 28, 2015 at 08:47 UTC
    The original code by BrowserUk works fine with the given sets of ids. What you have in your data? ie @idlist

    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      It has a list of user id numbers
      ranging from 1 to 70000 with not all numbers used up.
      Only 8436 differnt numbers between this range had been used.

Re: Understanding this code
by Ea (Chaplain) on Sep 28, 2015 at 11:18 UTC
    My grasp of postfix for is sometimes a little fuzzy, but if you re-write
    push @missing_ids, $idslist[ $_ ] +1 .. $idslist[ $_+1 ] -1 for 0 .. $ +#idslist-1;
    as
    for ( 0 .. $#idslist-1 ) { push @missing_ids, $idslist[ $_ ] +1 .. $idslist[ $_+1 ] -1; }
    I could see why @missing_ids is bigger. For every element of @idslist, you are pushing consecutive numbers/letters between $idslist[ $_ ] +1 and $idslist[ $_+1 ] -1, which could be very large indeed. How's that?

    Sometimes I can think of 6 impossible LDAP attributes before breakfast.

    http://ldapcon.org/2015 is just an excuse to enjoy November in sunny Edinburgh

A reply falls below the community's threshold of quality. You may see it by logging in.