开发者

How can I check if a value is in a list in Perl?

开发者 https://www.devze.com 2022-12-27 19:10 出处:网络
I have a file in which every line is an integer which represents an id. What 开发者_JAVA技巧I want to do is just check whether some specific ids are in this list.

I have a file in which every line is an integer which represents an id. What 开发者_JAVA技巧I want to do is just check whether some specific ids are in this list. But the code didn't work. It never tells me it exists even if 123 is a line in that file. I don't know why? Help appreciated.

open (FILE, "list.txt") or die ("unable to open !");

    my @data=<FILE>;

    my %lookup  =map {chop($_) => undef} @data;

    my $element= '123';
    if (exists $lookup{$element})
    {
        print "Exists";
    }

Thanks in advance.


You want to ensure you make your hash correctly. The very outdated chop isn't what you want to use. Use chomp instead, and use it on the entire array at once and before you create the hash:

 open my $fh, '<', 'list.txt' or die "unable to open list.txt: $!";
 chomp( my @data = <$fh> );
 my $hash = map { $_, 1 } @data;


With Perl 5.10 and up, you can also use the smart match operator:

my $id = get_id_to_check_for();
open my $fh, '<', 'list.txt' or die "unable to open list.txt: $!";
chomp( my @data = <$fh> );
print "Id found!" if $id ~~ @data;


perldoc -q contain


chop returns the character it chopped, not what was left behind. You perhaps want something like this:

my %lookup = map { substr($_,0,-1) => undef } @data;

However, generally, you should consider using chomp instead of chop to do a more intelligent CRLF removal, so you'd end up with a line like this:

my %lookup =map {chomp; $_ => undef } @data;


Your problem is that chop returns the character chopped, not the resulting string, so you're creating a hash with a single entry for newline. This would be obvious in debugging if you used Data::Dumper to output the resulting hash.

Try this instead:

my @data=<FILE>;
chomp @data;

my %lookup = map {$_ => undef} @data;


This should work... it uses first in List::Util to do the searching, and eliminates the initial map (this is assuming you don't need to store the values for something else immediately after). The chomp is done while searching for the value; see perldoc -f chomp.

use List::Util 'first';
open (my $fh, 'list.txt') or die 'unable to open list.txt!';

my @elements = <$fh>;

my $element = '123';
if (first { chomp; $_ eq $element } @elements)
{
    print "Exists";
}


This one may not exactly match your specific problem, but if your integer numbers need to be counted, you might even use the good old "canonical" perl approach:

 open my $fh, '<', 'list.txt' or die "unable to open list.txt: $!";

 my %lookup;
 while( <$fh> ) { chomp; $lookup{$_}++ }   # this will count occurences if ints

 my $element = '123';
 if( exists $lookup{$element} ) {
    print "$element $lookup{$element} times there\n" 
 }

This might even be in some circumstances faster than solutions with intermediate array.

Regards

rbo

0

精彩评论

暂无评论...
验证码 换一张
取 消