Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
Perl Monk, Perl Meditation
 
PerlMonks  

compare two strings and return only he unique values.

by Learnlot1 (Initiate)
on Feb 03, 2013 at 19:10 UTC ( #1016850=perlquestion: print w/ replies, xml ) Need Help??
Learnlot1 has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to display unique values from two strings "ABCDE", "BCDEO" to return "AO" with the below code. I am running out of ideas and I would appreciate some help. Thank you in advace!
#!/usr/bin/perl use strict; use warnings; my ($str1, $str2) = ("ABCDE", "BBBBB"); print join '', In_Common2($str1, $str2); sub In_Common2 { my ($str1, $str2) = @_; (my $common = reverse $str2) =~ s/[^$str1]|(.)(?=.*\1)//g; return scalar reverse $common; } print $str2; print join '', In_Common2($str1, $str2);

Comment on compare two strings and return only he unique values.
Download Code
Re: compare two strings and return only he unique values.
by tobyink (Abbot) on Feb 03, 2013 at 19:20 UTC
    use 5.010; use strict; use warnings; my ($str1, $str2) = ("ABCDE", "BCDEO"); my %in_str1 = map { $_ => 1 } split //, $str1; my %in_str2 = map { $_ => 1 } split //, $str2; my @unique; for my $letter (keys %in_str1, keys %in_str2) { unless ( $in_str1{$letter} and $in_str2{$letter} ) { push @unique, $letter; } } say "Unique letters: @unique";
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: compare two strings and return only he unique values.
by blue_cowdawg (Prior) on Feb 03, 2013 at 19:33 UTC
        I am trying to display unique values from two strings "ABCDE", "BCDEO" to return "AO" with the below code

    #!/usr/bin/perl -w use strict; use warnings; my $string1="abcdef"; my $string2="defghi"; my @ary=split(//,$string1); push @ary,split(//,$string2); my %een=(); map{ $een{$_}++ } @ary; my @unique=(); foreach (@ary){ next unless $een{$_} == 1; push @unique,$_; } printf "%s\n",join(",",@unique);
    Hashes are our friends....


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      Won't show "a" when:

      my $string1="abcdefa"; my $string2="defghi";
            Won't show "a" when:

        That's because "a" isn't unique. :)

        printf "%s\n",join(",", keys %een);
        would show "a" and all the other letters once.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: compare two strings and return only he unique values.
by smls (Pilgrim) on Feb 03, 2013 at 19:54 UTC

    You can also use List::Compare

    use List::Compare; my ($str1, $str2) = ("ABCDE", "BCDEO"); my @list1 = split //, $str1; my @list2 = split //, $str2; my @unique = List::Compare->new(\@list1, \@list2) ->get_symmetric_difference; say "Unique letters: @unique";
Re: compare two strings and return only he unique values.
by Not_a_Number (Parson) on Feb 03, 2013 at 20:22 UTC

    Yet another (short) way:

    my ( $str1, $str2 ) = ( 'ABCDE', 'BCDEO' ); my %count; $count{$_}++ for split //, $str1.$str2; print grep $count{$_} == 1, keys %count;

      Won't show "A" when:

      my ( $str1, $str2 ) = ( 'ABCDEA', 'BCDEO' );

        Yeah, I know. But the OP said:

        I am trying to display unique values from two strings

        So is 'A', in your dataset, unique or not?

        Depends upon a better spec, I suppose...

        Update: smls (below) already pointed this out;

Re: compare two strings and return only he unique values.
by smls (Pilgrim) on Feb 03, 2013 at 21:27 UTC

    Note:

    The various solutions posted above don't behave exactly the same. This is because the OP hasn't described the problem very precisely, so the commenters (myself included) have made implicit assumptions about the intended meaning of "unique values from two strings".

    Interpreting the term "values" in that quote as characters, there are at least two different meanings:

    • Characters that appear exactly once in one of the strings, and don't appear in the other.

      This is what the above solutions by blue_cowdawg and Not_a_Number do.

    • Characters that appear one or more times in one of the strings, and don't appear in the other.

      This is what the above solutions by tobyink and myself do.

    If "values" is supposed to mean something other than individual characters, simply adapt any of the above solutions by replacing the split(//, ...) calls with a statement that tokenizes the string into a list of values in the intended way.

    In case the strings are not intended to be tokenized in a fixed way, but instead what you are looking for is arbitrary text fragments that appear in one of the strings, but don't appear in that same spot in the other, look into Algorithm::Diff

      Excellent points++! It's evident, however, that the OP's considering the possibility of characters repeating in strings, as shown in the initial posting:

      my ($str1, $str2) = ("ABCDE", "BBBBB");
        *** Please delete. Misplaced dupe. ***
Re: compare two strings and return only he unique values.
by LanX (Abbot) on Feb 03, 2013 at 22:44 UTC
    please use real <code> tags and not &lt;code&gt;

    looks like you want the symmetric difference of two character sets

    DB<111> @a1=split//,$str1 => ("A", "B", "C", "D", "E") DB<112> @a2=split//,$str2 => ("B", "C", "D", "E", "O") DB<113> @h2{@a2}=() DB<114> @h1{@a1}=() DB<115> delete @h2{@a1} DB<116> delete @h1{@a2} DB<117> (keys %h1, keys %h2) => ("A", "O")

    see Using hashes for set operations... for background.

    UPDATE:

    seems like nobody mentioned that its a FAQ How do I compute the difference of two arrays? How do I compute the intersection of two arrays?

    UPDATE:

    Just in case you only want the unique characters in both strings:

    DB<137> $h{$_}++ for (split//,$str1),(split//,$str2) => "" DB<138> \%h => { A => 1, B => 2, C => 2, D => 2, E => 2, O => 1 } DB<139> grep {$h{$_}==1} keys %h => ("A", "O")

    oops basically already shown by Not_a_Number

    EDIT: one liner =)

    DB<146> grep {$h{$_}==1} map {$h{$_}++;$_} split//,$str1.$str2 => ("A", "O")

    Cheers Rolf

Re: compare two strings and return only he unique values.
by AnomalousMonk (Monsignor) on Feb 04, 2013 at 01:57 UTC

    Here's a substution-based version that may be somewhat along the lines Learnlot1 was thinking of originally. It does not generalize well to handling more than two strings as the split-to-hash approaches do. It suffers from the vagueness of the implied specification as other approaches do. But it works (for some definition of 'works').

    >perl -wMstrict -le "for my $ar_vector ( [ qw(ABCDE BCDEO) ], [ qw(ABCDE BBBBB) ], [ qw(ABCDEA BCDEO) ], ) { my ($s1, $s2) = @$ar_vector; printf qq{'$s1' '$s2' -> '%s' \n}, non_common($s1, $s2); } ;; sub non_common { my ($sa, $sb) = @_; ;; (my $a_sans_b = $sa) =~ s{ [\Q$sb\E]+ }{}xmsg; (my $b_sans_a = $sb) =~ s{ [\Q$sa\E]+ }{}xmsg; return $a_sans_b . $b_sans_a; } " 'ABCDE' 'BCDEO' -> 'AO' 'ABCDE' 'BBBBB' -> 'ACDE' 'ABCDEA' 'BCDEO' -> 'AAO'

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (15)
As of 2014-04-18 20:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (471 votes), past polls