Re: compare two strings and return only he unique values.
by tobyink (Canon) 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
| [reply] [d/l] |
Re: compare two strings and return only he unique values.
by smls (Friar) on Feb 03, 2013 at 19:54 UTC
|
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";
| [reply] [d/l] |
Re: compare two strings and return only he unique values.
by blue_cowdawg (Monsignor) 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
| [reply] [d/l] |
|
|
my $string1="abcdefa";
my $string2="defghi";
| [reply] [d/l] |
|
|
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
| [reply] [d/l] |
|
|
|
|
|
Re: compare two strings and return only he unique values.
by smls (Friar) 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
| [reply] [d/l] |
|
|
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");
| [reply] [d/l] |
|
|
*** Please delete. Misplaced dupe. ***
| [reply] |
Re: compare two strings and return only he unique values.
by Not_a_Number (Prior) on Feb 03, 2013 at 20:22 UTC
|
my ( $str1, $str2 ) = ( 'ABCDE', 'BCDEO' );
my %count;
$count{$_}++ for split //, $str1.$str2;
print grep $count{$_} == 1, keys %count;
| [reply] [d/l] |
|
|
my ( $str1, $str2 ) = ( 'ABCDEA', 'BCDEO' );
| [reply] [d/l] |
|
|
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;
| [reply] |
|
|
Re: compare two strings and return only he unique values.
by LanX (Saint) on Feb 03, 2013 at 22:44 UTC
|
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")
| [reply] [d/l] [select] |
Re: compare two strings and return only he unique values.
by AnomalousMonk (Archbishop) 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'
| [reply] [d/l] |