You're actually not matching anything. I added debug output to your code.
my @list = ( "one", "two", "three", "onefour", "one" );
foreach my $f (@list) {
say "f: $f";
my $length = length($f);
say "length: $length";
say "true { $length && $f} $_: " . ( $length && "$f" ) for @list;
my $count = true { $length && "$f" } @list;
say "count: $count";
if ( $count > 1 ) {
print "Error with: ", $f, " counted ", $count, " times!\n";
}
$count = 0;
}
Let's take a look:
f: one
length: 3
true { 3 && one} one: one
true { 3 && one} two: one
true { 3 && one} three: one
true { 3 && one} onefour: one
true { 3 && one} one: one
count: 5
Error with: one counted 5 times!
f: two
length: 3
true { 3 && two} one: two
true { 3 && two} two: two
true { 3 && two} three: two
true { 3 && two} onefour: two
true { 3 && two} one: two
count: 5
Error with: two counted 5 times!
f: three
length: 5
true { 5 && three} one: three
true { 5 && three} two: three
true { 5 && three} three: three
true { 5 && three} onefour: three
true { 5 && three} one: three
count: 5
Error with: three counted 5 times!
f: onefour
length: 7
true { 7 && onefour} one: onefour
true { 7 && onefour} two: onefour
true { 7 && onefour} three: onefour
true { 7 && onefour} onefour: onefour
true { 7 && onefour} one: onefour
count: 5
Error with: onefour counted 5 times!
f: one
length: 3
true { 3 && one} one: one
true { 3 && one} two: one
true { 3 && one} three: one
true { 3 && one} onefour: one
true { 3 && one} one: one
count: 5
Error with: one counted 5 times!
So you always have the length of the string $f, which is larger than 0 and hence evaluates as true in Perl. Then you have $f. Which is true also, because all strings that are not the empty string ('') are true.
You iterate over all elements in @list with the true function. The block always is true. So you always get the count of the number of elements in @list.
If you only want to remove double occurances, you can use a hash to count them.
my %count;
$count{$_}++ for @list;
my @unique = keys %count; # unsorted
# see Sobrique's answer with grep for sorted the same way as before
Then there is also uniq in List::MoreUtils.
my @unique = uniq @list;
If you want to know for each element if it is a substring of any other element, you can use Perl's builtin index, which finds the position of a string inside another string, and a grep.
foreach my $f (@list) {
if ( my @matches = grep { $_ ne $f && index( $_, $f ) > -1 } @list ) {
warn "$f is a substr of: @matches"; # will auto-join on $,
}
}
__END__
one is a substr of: onefour at /code/scratch.pl line 91.
one is a substr of: onefour at /code/scratch.pl line 91.
Now of course this doesn't get that element 0 and 4 are both "one" because of the ne. Note that index returns -1 if there is no match at all.
Edit after your comment on Sobrique's answer:
To only get warnings if there are duplicates (or substr duplicates), simply count them. There is no modification happening anywhere:
my @list = ( "one", "two", "three", "onefour", "one" );
my %count;
$count{$_}++ for @list;
warn sprintf 'Number of duplicates: %d', @list - keys %count if @list != keys %count;
my $count_substr;
foreach my $f (@list) {
$count_substr++
if grep { $_ ne $f && index( $_, $f ) > -1 } @list;
}
warn sprintf 'Number of substring duplicates: %d', $count_substr if $count_substr;