in reply to Seeking the longest string in an array

use strict; my @data = qw/a mnk ab m b bc abcd cd bcd bd m nk/; @data = sort {length($b) <=> length($a)} @data; my @result = (); while (@data) { push @result, $data[0]; @data = grep { $data[0] !~ /\Q$_\E/ } @data; } print "@result\n";
Update
Changed to reflect ikegami's commets.
Please explain the /\Q...\E/
I'm not so sure about the /../i. The OP may want it to be case sensitive.
Thanks.

Update2:
mpeters,
Having read your post and jenda's above, I've incorporated 'index'. Your solution, as it stands, will not work because index returns a position on match and the grep expression needs to return false. So I did it this way.
... while (@data) { push @result, $data[0]; @data = grep { index($data[0], $_) == -1 } @data; } ...

Replies are listed 'Best First'.
Re^2: Seeking the longest string in an array
by ikegami (Patriarch) on Dec 11, 2004 at 23:38 UTC

    Change cmp to <=>.

    Change /.../ to /\Q...\E/.

    Change /.../ to /.../i.

    O(N*log(N) + N2*M2). That's a worse worst case than the OP. In practice, though, yours would be faster, because the inner loop will be get much smaller than N very fast.

      change $data[0] =~ /\Q$_\E/ to index($data[0], $_).

      Should be faster.
        nope, won't work. He's doing case-insensitive searches.
Re^2: Seeking the longest string in an array
by Jenda (Abbot) on Dec 12, 2004 at 13:42 UTC

    The original code searched for the substrings case insensitively so you'd have to uc() or lc() the strings before passing to index() if you want to behave the same. There is also one more thing that might be worth trying. We might create a character bitmap of all strings beforehand and then only search for the substring if the longer string contains all the characters that the substring does:

    use strict; use Bit::Vector; my @data = qw/a mnk ab m b bc abcd cd bcd bd m nk/; @data = sort {length($b) <=> length($a)} @data; @data = map [$_, uc($_), Bit::Vector->new_Enum(256, join(',', map ord( +$_), (split //, uc($_))))->Block_Read()], @data; my @result = (); while (@data) { push @result, $data[0][0]; @data = grep { ($data[0][2] & $_->[2]) ne $_->[2] or index($data[0 +][1], $_->[1]) == -1 } @data; } print "@result\n";
    Whether and how much would this help depends on the strings. In this case I saved just 5 calls to index() from the original 18.

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson