Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Comparing strings

by tanyeun (Sexton)
on Jul 24, 2006 at 14:52 UTC ( [id://563283]=perlquestion: print w/replies, xml ) Need Help??

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

I have two arrays @a,@b
@a = qw/AA12 BB13 CC14 DD15/ @b = qw/aa1 aa2 aa12 bb13/
I use
if($a[$i] =~ /$b[$j]/i) trying to find AA12, BB13 in @a
correspond to aa12, bb13 in @b
but it will return true when AA12 encounter aa1
how should I do?
Thanks

Replies are listed 'Best First'.
Re: Comparing strings
by jdporter (Paladin) on Jul 24, 2006 at 15:08 UTC

    If the idea is to find the common elements, with case insensitivity, then you can use hashes. Let the keys be uppercased for all entries, and the values be the originals. Then you can use standard techniques for set comparison using hashes.

    my %a = map {( uc($_) => $_ )} @a; my %b = map {( uc($_) => $_ )} @b; my @common_keys = grep { exists $a{$_} } keys %b; my @a_values_seen_in_b = @a{ @common_keys }; my @b_values_seen_in_a = @b{ @common_keys };

    There are also modules on CPAN for tied hashes which allow you to store and retrieve keys case-insensitively; but I don't think they're necessary for this problem.

    We're building the house of the future together.
Re: Comparing strings
by Corion (Patriarch) on Jul 24, 2006 at 14:55 UTC

    You want to make sure that the whole string matches and not just a substring. You can use the "anchors" ^ (start of string) and $ (end of string) for that:

    if($a[$i] =~ /^$b[$j]$/i)

    But if you want to compare the whole string, a direct comparison of the upper case variants is more straightforward:

    if(uc $a[$i] eq uc $b[$j]) { ... }

      Does @b contain regexp or strings? If it contains regexps, your second snippet doesn't work. If it contains strings, your first snippet is broken. Sounds like @b contains strings, so the solutions would be

      if ($a[$i] =~ /^\Q$b[$j]\E\z/i)

      and (the much faster)

      if (uc $a[$i] eq uc $b[$j])

      You can only omit the quoting provided by \Q...\E is you are sure @b doesn't contains any meta characters.

Re: Comparing strings
by jaa (Friar) on Jul 24, 2006 at 15:06 UTC
    A lowercase eq will be faster than a regex:
    #!/usr/local/bin/perl -slw use strict; use Benchmark qw[ cmpthese ]; our @a = qw/AA12 BB13 CC14 DD15/; our @b = qw/aa1 aa2 aa12 bb13/; sub regex { my @match; for my $i ( 0 .. $#a ) { for my $j ( 0 .. $#b ) { if ( $a[$i] =~ m/^$b[$j]$/i ) { push @match, "$i -> $j"; } } } return @match; } sub lccmp { my @match; for my $i ( 0 .. $#a ) { for my $j ( 0 .. $#b ) { if ( lc($a[$i]) eq lc($b[$j]) ) { push @match, "$i -> $j"; } } } return @match; } cmpthese -1, { lccmp => q[ lccmp() ], regex => q[ regex() ], };
    Retults:
    Rate regex lccmp regex 8083/s -- -82% lccmp 45997/s 469% --
Re: Comparing strings
by gasho (Beadle) on Jul 24, 2006 at 15:06 UTC
    Try this
    use List::Compare; @a = qw/AA12 BB13 CC14 DD15/; @b = qw/AA1 AA2 AA12 BB13/; $element = List::Compare->new(\@a, \@b); #@UF = $element->get_unique; @CB = $element->get_intersection; print join "\n", @CB;
Re: Comparing strings
by mantra2006 (Hermit) on Jul 24, 2006 at 19:47 UTC
    if its an array you can compare both in the following way
    @union = @intersection = @difference = (); %count = (); foreach $element (@a, @b) { $count{$element}++ } foreach $element (keys %count) { push @union, $element; push @{ $count{$element} > 1 ? \@intersection : \@difference } +, $element; } foreach $int (@difference){ if ($int ne " "){ @fname = split(/ /, $int); print "\n difference elements --> $fname[0]\n"; } }

    Edited by planetscape - added code tags

      thanks, monks ^^
      although some of your suggestions
      are above my level
      I'll work hard to keep up with it
Re: Comparing strings
by rsriram (Hermit) on Jul 25, 2006 at 08:50 UTC

    Hi tanyeun, Here is a simple way to compare your arrays.

    my @arr1= sort (@$a); my @arr2= sort (@$b);
        for my $x (0..$#b)
        {
            if ($b[$x] ne $a[$x])
            {
            print ("Mismatch in $arr1[$x]");
            }
        }

    Here, I am sorting both the arrays, then using a for loop to run the execution the number of times till all the elements are encountered. Then I am using a if condition to check whether each and every element in the array matches with its corresponding element in the second array. If needed, you can also add the following codes before the above lines

    if ($#arr1 != $#arr2)
    {
    print "count of elements in two arrays do not match";
    exit;
    }

    With this, I am ensuring the number of elements in array 'a' matches with the number of elements in array 'b' before the actual one-to-one match is made.

    Also consider having a smart solution!!! Use Array::Compare. Hope this helps

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://563283]
Approved by wfsp
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-25 23:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found