Loading ...
Sorry, an error occurred while loading the content.

RE: [PBML] easy way to find out if a variable is in an array?

Expand Messages
  • Mike Payne
    I d be interested in hearing everyone s thoughts about this way of solving the problem, by the way... I m wondering how efficient it is compared to the other
    Message 1 of 5 , Oct 26, 2000
    • 0 Attachment
      I'd be interested in hearing everyone's thoughts about this way of solving
      the problem, by the way... I'm wondering how efficient it is compared to the
      other solutions offered.

      ----------------------------------------------
      Mike "Theseus" Payne
      theseus@...
      http://www.simpleminded.org/
      ----------------------------------------------

      -----Original Message-----
      From: Mike Payne [mailto:theseus@...]
      Sent: Thursday, October 26, 2000 9:09 PM
      To: perl-beginner@egroups.com
      Subject: RE: [PBML] easy way to find out if a variable is in an array?


      Or coming from a completely different side... You could just do this...

      $_ = join(' ',@where_it_may_be);
      if (/$what_i_want/) {
      print "it's there";
      }
      else {
      print "it's not there";
      }

      I don't know how efficient this is in terms of CPU time, but it's an idea.

      ----------------------------------------------
      Mike "Theseus" Payne
      theseus@...
      http://www.simpleminded.org/
      ----------------------------------------------

      -----Original Message-----
      From: jandrew [mailto:jandrew]On Behalf Of Andrew Johnson
      Sent: Thursday, October 26, 2000 8:57 PM
      To: perl-beginner@egroups.com
      Subject: Re: [PBML] easy way to find out if a variable is in an array?


      tbarron@... wrote:
      ! binliu@... wrote:
      ! > Sure I can use foreach and compare, but is there a way that I could
      ! > not use a loop?
      ! > I think I could use grep but I haven't figure out how.
      !
      ! You mean like this?
      !
      ! if (grep(/$what_I_want/, @where_it_may_be))
      ! {
      ! print("It's there\n");
      ! }
      ! else
      ! {
      ! print("It's not there\n");
      ! }

      Using grep() for this is the wrong approach -- if the element is
      at or near the beginning of the list, grep() still has to check every
      element (it can't jump out if it found it). Use a foreach loop and
      'last' to jump out of the loop if you find it, or perhaps use a hash
      to store your data to begin with (hashes are designed for lookups,
      arrays are not).

      The perlfaq4.pod document gives a more detailed answer to this question.
      Try:

      perldoc perlfaq4

      or

      man perlfaq4

      (depending on your preference and system) and search for the heading:

      How can I tell whether a list or array contains a certain element?

      regards,
      andrew

      --
      Andrew L. Johnson http://members.home.net/andrew-johnson/
      Some people, when confronted with a problem, think 'I know,
      I'll use regular expressions.' Now they have two problems.
      -- Jamie Zawinski, on comp.lang.emacs
    • Andrew Johnson
      Mike Payne wrote: ! Or coming from a completely different side... You could just do this... ! ! $_ = join( ,@where_it_may_be); ! if (/$what_i_want/) { !
      Message 2 of 5 , Oct 26, 2000
      • 0 Attachment
        Mike Payne wrote:
        ! Or coming from a completely different side... You could just do this...
        !
        ! $_ = join(' ',@where_it_may_be);
        ! if (/$what_i_want/) {
        ! print "it's there";
        ! }

        Followed by this:

        ! I'd be interested in hearing everyone's thoughts about this way of solving
        ! the problem, by the way... I'm wondering how efficient it is compared to the
        ! other solutions offered.

        The Benchmark module can be used to answer questions about relative speed
        efficiency -- but before you do that, please read on...

        In the first place, since we are looking for strings, not patterns
        (at least as I understand the OP), then using a regex will be slower
        than using index() -- your method above would be faster if written
        along the lines of:

        $_ = join(' ', @array);
        if ( index($_,$search) >= 0 ) {
        print "found it\n";
        }

        Now, strictly from a speed point of view, this isn't a bad solution.
        However, from a memory point of view we already have the array in
        memory and now we also have to construct a string of the same data
        in memory (what if the array is large). The method of looping and
        bailing out if we find it is more memory friendly -- it will also be
        quick if the element exists nearer the beginning of the list (and it
        won't be much slower if it is farther along, or doesn't exist in
        the list).

        BUT (and that's a big but), more important than mere efficiency
        concerns (be it speed or memory) is *correctness*. Joining the list
        into a string and then searching for a substring has a very real
        potential for failure. Consider the following example:

        my @array = ('abc' .. 'acd'); # 28 element list: abc abd abe...
        my $search = 'c ab';
        $_ = join(' ',@array);
        if (index($_, $search) >= 0 ) {
        print "Found it\n";
        }

        The above will print "Found it" even though there is no string 'c ab'
        in the list -- because when 'abc' and 'abd' are joined with a space
        we get the string 'abc abd', which does contain the substring 'c ab'.

        Of course, you can try to pick a join-character that you hope won't
        allow this to occur -- but if the array is derived from outside data,
        and the search string is obtained from user input or elsewhere, you
        have a very real potential for unpredictable failure.

        If we just use a simple bail-out loop, we only test real elements of
        the array against the search criteria, using memory that is already
        allocated (plus a little loop overhead), and we only test as many
        elements as necessary:

        foreach my $elem (@array) {
        if ($elem eq $search) {
        print "Found it\n";
        last;
        }
        }

        This way is also easily modified to find out which array element
        is the matching one:

        my $found_it;
        for my $index (0 .. $#array) {
        if($array[$index] eq $search) {
        $found_it = $index;
        last;
        }
        }
        print "Found it at: $found_it\n" if defined $found_it;

        Of course, as with my last post (and the perlfaq4 suggestion) -- if
        such queries are to be made often, storing the data in a hash rather
        than an array is likely the most convenient and efficient solution.

        I hope this helps.

        regards,
        andrew

        --
        Andrew L. Johnson http://members.home.net/andrew-johnson/
        Some people, when confronted with a problem, think 'I know,
        I'll use regular expressions.' Now they have two problems.
        -- Jamie Zawinski, on comp.lang.emacs
      Your message has been successfully submitted and would be delivered to recipients shortly.