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

Hello,
Is there a way by making use of s/// , I can get rid of duplicate characters in a string ?
InPut : $str = "abcdefghiaabccdjklm"; OutPut : $str="efghijklm";
So I did try something like this below , but it requires me to do the replacement repeatedly to get rid of all repeating characters
Not sure if this can be done in one go itself ?
Original String : my $str = "abcdeffghijkllmnoppqestqaserb"; 1st iteration : $str =~ s/(\w)(.*)\1/$2/g; Output : bcdeffghijkllmnoppqestqserb 2nd Iteration : $str =~ s/(\w)(.*)\1/$2/g; OutPut : cdeffghijkllmnoppqestqser 3rd Iteration : $str =~ s/(\w)(.*)\1/$2/g; OutPut : cdffghijkllmnoppqestqsr 4th Iteration : Gets rid of consecutive elements $str =~ s/(\w)(.*)\1/$2/g; OutPut: cdghijkmnoestsr

Replies are listed 'Best First'.
Re: How to remove duplicate characters in a string in place
by poj (Abbot) on Feb 20, 2016 at 17:49 UTC

    If you have a recent version of List::MoreUtils

    use List::MoreUtils qw( singleton ); my $str = join '',singleton split '',"abcdefghiaabccdjklm"; print $str;
    poj
Re: How to remove duplicate characters in a string in place
by toolic (Bishop) on Feb 20, 2016 at 17:37 UTC
    I can't think of a way to do it with a single s///, but this works:
    use strict; use warnings; my $str = "abcdefghiaabccdjklm"; my @chars = split //, $str; my %uniq; $uniq{$_}++ for @chars; $str = ''; for (@chars) { $str .= $_ unless $uniq{$_} > 1; } print $str; __END__ efghijklm
Re: How to remove duplicate characters in a string in place
by duelafn (Parson) on Feb 20, 2016 at 17:55 UTC

    Still executes in a loop, but gets all instances of each letter each time (thus avoids the even/odd issue you have).

    use 5.010; my $str = "abcdefghiaabccdjklm"; my $substr; $substr = "" while $str =~ s/(.)(?:(.*?)\1(?{ $substr .= $^N }))+/$sub +str/; say $str;

    Good Day,
        Dean

Re: How to remove duplicate characters in a string in place
by hdb (Monsignor) on Feb 20, 2016 at 17:58 UTC

    I have no better solution than to do a loop but your regex always removes pairs of characters, so if you have an odd number of a character one will remain. Is that what you want?

Re: How to remove duplicate characters in a string in place -- oneliner
by Discipulus (Canon) on Feb 20, 2016 at 21:22 UTC
    Sorry if i cannot make use s/// but unique/duplicate call for hashes in my mind
    # warning win32 doublequote perl -e "print grep {$res{$_}==1} map {++$res{$_};$_} split '',$ARGV[0 +]" abcdefghiaabccdjklm efghijklm
    PS sorry if i've not seen this is identical in the approach to the toolic's one

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: How to remove duplicate characters in a string in place
by Anonymous Monk on Feb 20, 2016 at 19:30 UTC

    A solution with s/// seems inefficient. And the loop is probably unavoidable: you'd need either variable lookbehind, or multiple matches on same text. Anyway:

    my $str = "abcdefghiaabccdjklm"; print "Input : $str\n"; 1 while $str =~ s/(.)(.*?(?=\g1))((?=.+?\g1)|.)/$2/; print "Output: $str\n";

Re: How to remove duplicate characters in a string in place
by kcott (Archbishop) on Feb 22, 2016 at 06:43 UTC

    G'day punitpawar,

    "Is there a way by making use of s/// ..."

    You're starting with a solution and then trying to make it fit a problem. This is back-to-front: start with a problem and then find an appropriate solution.

    The output of your second example (cdghijkmnoestsr) contains an 'e' which shouldn't be there: the original string (abcdeffghijkllmnoppqestqaserb) contains three 'e's.

    As others have already noted, s/// does not seem appropriate. Here's how I might have tackled this problem:

    #!/usr/bin/env perl -l use strict; use warnings; my @test_strings = qw{ abcdefghiaabccdjklm abcdeffghijkllmnoppqestqaserb }; remove_duplicate_chars($_) for @test_strings; sub remove_duplicate_chars { my $str = shift; my %seen; my @chars = grep { ! $seen{$_}++ } split //, $str; my $uniq = join '', grep { $seen{$_} == 1 } @chars; print "IN: $str"; print "OUT: $uniq"; return; }

    Output:

    IN: abcdefghiaabccdjklm OUT: efghijklm IN: abcdeffghijkllmnoppqestqaserb OUT: cdghijkmnotr

    — Ken

Re: How to remove duplicate characters in a string in place
by tybalt89 (Monsignor) on Apr 03, 2017 at 17:28 UTC
    #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1155716 use strict; use warnings; my $input = "abcdefghiaabccdjklm"; my $want = "efghijklm"; print $input; $input =~ s/.(??{ -1 == index("$`$'", $&) && '(*FAIL)' })//g; print $input; print $want; $input eq $want and print "Match!";

    hehehe