http://qs321.pair.com?node_id=499331

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

#what is the simplest way to do this? I have a function called "found" but I think the grep function might be able to be used for it but I don't know how...

@array = (1,2); $number = 3; # HOW TO DO THIS? check to see if $number is in @array print "found\n" if found($number, @array );

Replies are listed 'Best First'.
Re: how to quickly tell if number is in an array
by jdporter (Paladin) on Oct 12, 2005 at 02:50 UTC
Re: how to quickly tell if number is in an array
by GrandFather (Saint) on Oct 12, 2005 at 01:02 UTC
    print "found\n" if grep {$_ == 3} @array;

    Perl is Huffman encoded by design.

      If his quickly means faster, let's compare those two solutions:

      use Benchmark qw(timethese); use strict; use warnings; my @array = (1 .. 100000); timethese(100, {granfather => \&grandfather, usual => \&usual}); sub grandfather { return 1 if grep {$_ == 100000} @array; } sub usual { for my $a (@array) { return 1 if ($a == 100000); } return 0; }

      If the element we serach is at the end, grandfather's is a little bit faster:

      Benchmark: timing 100 iterations of granfather, usual... granfather: 4 wallclock secs ( 3.58 usr + 0.00 sys = 3.58 CPU) @ 27 +.95/s (n=1 00) usual: 4 wallclock secs ( 4.13 usr + 0.00 sys = 4.13 CPU) @ 24 +.24/s (n=1 00)

      But if you change the above code to search for 3 (at the beginning of the array), then the usual way is much faster:

      Benchmark: timing 100 iterations of granfather, usual... granfather: 3 wallclock secs ( 3.58 usr + 0.00 sys = 3.58 CPU) @ 27 +.95/s (n=1 00) usual: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU) (warning: too few iterations for a reliable count)

      With something in the middle say 50000, the usual way is still close to 50% faster.

      Benchmark: timing 100 iterations of granfather, usual... granfather: 4 wallclock secs ( 3.69 usr + 0.03 sys = 3.72 CPU) @ 26 +.89/s (n=1 00) usual: 2 wallclock secs ( 2.08 usr + 0.00 sys = 2.08 CPU) @ 48 +.12/s (n=1 00)

      Now you know which direction it is pointing to ;-)

        A good reply pg, and valuable in pointing out that "simplest" is not always "best" for given values of simplest and best. (In fact simplest is often "worst".)

        OP did however ask about simplest and expressed interest in how grep could be used. Now if you could benchmark "simplest" that would be a neat trick.


        Perl is Huffman encoded by design.
Re: how to quickly tell if number is in an array
by ioannis (Abbot) on Oct 12, 2005 at 01:25 UTC
    Fine, you requested an easy method; although, faster methods could be implementd with map or grep, assuming we don't have detailed knowledge if elements are already sorted in the array. Here is on easy method:
    my @arr = 1..20 ; my $num = 4; my %h ; @h{@arr} = (undef) x @arr; exists $h{$num} and print qq(Yes, $num exists inside \@arr)
Re: how to quickly tell if number is in an array
by ioannis (Abbot) on Oct 12, 2005 at 04:59 UTC
    While countless methods exist to test for membership in the list, it is worthy to remember the obvious: when checking for elemenet 0, we should not forget to test using defined. Here is an example, this time using first from List::Util:
    use List::Util 'first'; my @arr = (1..2, 0, 4); my $num = 0; defined first {$_==$num} @arr and print 'found';
Re: how to quickly tell if number is in an array
by McDarren (Abbot) on Oct 12, 2005 at 01:17 UTC
    print "found\n" if grep($number, @array);
      my @array = (1, 2); print "found\n" if grep(3, @array);

      which prints found may not be what OP expects


      Perl is Huffman encoded by design.
        whoops!
        Okay... how about...
        print "found\n" if grep(/^$number\$/, @array);
Re: how to quickly tell if number is in an array
by Limbic~Region (Chancellor) on Oct 12, 2005 at 14:25 UTC
Re: how to quickly tell if number is in an array
by Zaxo (Archbishop) on Oct 13, 2005 at 00:12 UTC

    The methods shown so far are best if the test only occurs a few times in the program and if the list is short. For frequent use, make a hash with the array elements as keys, and check for existence of the test value as a key.

    my @array = (1,2,5..20,42..99); my %element; @element{@array} = (); print exists $element{$num}? "$num found": "$num not found";

    After Compline,
    Zaxo

      For frequent use, make a hash

      Yes. (But don't do this with refs.) There are compromises too, like binary searches and Tie::IxHash and other modules. Lots of different trade-offs can be made between ordering restrictions, code complexity, execution time, and space requirements. The trick is picking the right one. :-)

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: how to quickly tell if number is in an array
by Rajeshk (Scribe) on Oct 12, 2005 at 10:31 UTC
    Hi,

    Try this code..
    @a = (1,3,5);
    $number = 3;

    if((grep /$number/, @array)){
    print "Found";
    }else{
    print "Not Found";
    }


    Thanks
    Rajesh.K