Strip a set of characters from a string

From Rosetta Code
Task
Strip a set of characters from a string
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to create a function that strips a set of characters from a string. The function should take two arguments: the first argument being a string to stripped and the second, a string containing the set of characters to be stripped. The returned string should contain the first string, stripped of any characters in the second argument:

<lang pseudocode> print stripchars("She was a soul stripper. She took my heart!","aei") Sh ws soul strppr. Sh took my hrt!</lang>

Ada

<lang Ada>with Ada.Text_IO;

procedure Strip_Characters_From_String is

  function Strip(The_String: String; The_Characters: String)
                 return String is
     Keep:   array (Character) of Boolean := (others => True);
     Result: String(The_String'Range);
     Last:   Natural := Result'First-1;
  begin
     for I in The_Characters'Range loop
        Keep(The_Characters(I)) := False;
     end loop;
     for J in The_String'Range loop
        if Keep(The_String(J)) then
           Last := Last+1;
           Result(Last) := The_String(J);
        end if;
     end loop;
     return Result(Result'First .. Last);
  end Strip;
  S: String := "She was a soul stripper. She took my heart!";

begin -- main

  Ada.Text_IO.Put_Line(Strip(S, "aei"));

end Strip_Characters_From_String;</lang>

Output:

> ./strip_characters_from_string 
Sh ws  soul strppr. Sh took my hrt!

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

<lang algol68>#!/usr/local/bin/a68g --script #

PROC strip chars = (STRING mine, ore)STRING: (

 STRING out := "";
 FOR i FROM LWB mine TO UPB mine DO
   IF NOT char in string(mine[i], LOC INT, ore) THEN
     out +:= mine[i]
   FI
 OD;
 out[@LWB mine]

);

printf(($gl$,stripchars("She was a soul stripper. She took my heart!","aei")))</lang> Output:

Sh ws  soul strppr. Sh took my hrt!

AutoHotkey

<lang AutoHotkey>MsgBox % stripchars("She was a soul stripper. She took my heart!","aei")

StripChars(string, charsToStrip){

  Loop Parse, charsToStrip
     StringReplace, string, string, % A_LoopField, , All
  return string

}</lang> Output:

Sh ws  soul strppr. Sh took my hrt!

AWK

<lang AWK>#!/usr/bin/awk -f BEGIN {

  x = "She was a soul stripper. She took my heart!";
  print x;
  gsub(/[aei]/,"",x);
  print x;

}</lang>

Output:

She was a soul stripper. She took my heart!
Sh ws  soul strppr. Sh took my hrt!

BASIC

Works with: QBasic

<lang qbasic>DECLARE FUNCTION stripchars$(src AS STRING, remove AS STRING)

PRINT stripchars$("She was a soul stripper. She took my heart!", "aei")

FUNCTION stripchars$(src AS STRING, remove AS STRING)

   DIM l0 AS LONG, t AS LONG, s AS STRING
   s = src
   FOR l0 = 1 TO LEN(remove)
       DO
           t = INSTR(s, MID$(remove, l0, 1))
           IF t THEN
               s = LEFT$(s, t - 1) + MID$(s, t + 1)
           ELSE
               EXIT DO
           END IF
       LOOP
   NEXT
   stripchars$ = s

END FUNCTION</lang>

Output:

Sh ws  soul strppr. Sh took my hrt!

See also: Liberty BASIC, PureBasic

Bracmat

This solution handles Unicode (utf-8) characters. Optimizations are: (1) the chars string is hard-coded into the pattern before the pattern is used in the match expression, (2) the output characters are stacked (cheap) rather than appended (expensive). The result string is obtained by stringizing the stack and reversing. To make multibyte characters survive, they are reversed before being put onto the stack. A problem is that this code is negligent of diacritical marks. <lang bracmat>( ( strip

 =   string chars s pat
   .     !arg:(?string.?chars)
       & :?s
       &     
           ' ( ?
               ( %
               : [%( utf$!sjt
                   & ( @($chars:? !sjt ?)
                     | rev$!sjt !s:?s
                     )
                   & ~
                   )
               )
               ?
             )
         : (=?pat)
       & @(!string:!pat)
     | rev$(str$!s)
 )

& out

 $ (strip$("Аппетит приходит во время еды".веп)

);</lang> Output:

Атит риходит о рмя ды

C

<lang c>#include <string.h>

  1. include <stdio.h>
  2. include <stdlib.h>
 /* removes all chars from string */

char *strip_chars(char *string, char *chars) {

 char * newstr = malloc(strlen(string) + 1);
 int counter = 0;
 for ( ; *string; string++) {
   if (!strchr(chars, *string)) {
     newstr[ counter ] = *string;
     ++ counter;
   }
 }
 newstr[counter] = 0;
 return newstr;

}

int main(void) {

 char *new = strip_chars("She was a soul stripper. She took my heart!", "aei");
 printf("%s\n", new);
 free(new);
 return 0;

}</lang>

Result:

Sh ws  soul strppr. Sh took my hrt!

With table lookup

<lang C>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>

char *strip(char * str, char *pat) { /* char replacement is typically done with lookup tables if * the replacement set can be large: it turns O(m n) into * O(m + n). * If same replacement pattern is going to be applied to many * strings, it's better to build a table beforehand and reuse it. * If charset is big like unicode, table needs to be implemented * more efficiently, say using bit field or hash table -- it * all depends on the application. */ int i = 0, tbl[128] = {0}; while (*pat != '\0') tbl[(int)*(pat++)] = 1;

char *ret = malloc(strlen(str)); do { if (!tbl[(int)*str]) ret[i++] = *str; } while (*(str++) != '\0');

/* assuming realloc is efficient and succeeds; if not, we could * do a two-pass, count first, alloc and strip second */ return realloc(ret, i); }

int main() { char * x = strip("She was a soul stripper. She took my heart!", "aei"); printf(x); free(x);

return 0; }</lang>Output same as above.

C++

Works with: C++11

<lang cpp>#include <algorithm>

  1. include <iostream>
  2. include <string>

std::string stripchars(std::string str, const std::string &chars) {

   str.erase(
       std::remove_if(str.begin(), str.end(), [&](char c){
           return chars.find(c) != std::string::npos;
       }),
       str.end()
   );
   return str;

}

int main() {

   std::cout << stripchars("She was a soul stripper. She took my heart!", "aei") << '\n';
   return 0;

}</lang> Output:

Sh ws  soul strppr. Sh took my hrt!

C#

<lang C sharp> using System;

public static string RemoveCharactersFromString(string testString, string removeChars) {

   char[] charAry = removeChars.ToCharArray();
   string returnString = testString;
   foreach (char c in charAry)
   {
       while (returnString.IndexOf(c) > -1)
       {
           returnString = returnString.Remove(returnString.IndexOf(c), 1);
       }
   }
   return returnString;

} </lang>

Usage: <lang C sharp> using System;

class Program {

   static void Main(string[] args)
   {
       string testString = "She was a soul stripper. She took my heart!";
       string removeChars = "aei";
       Console.WriteLine(RemoveCharactersFromString(testString, removeChars));
   }

} </lang> Output:

Sh ws  soul strppr. Sh took my hrt!

Using Regex: <lang C sharp> using System; using System.Text.RegularExpressions;

private static string RegexRemoveCharactersFromString(string testString, string removeChars) {

   string pattern = "[" + removeChars + "]";
   return Regex.Replace(testString, pattern, "");

}</lang>

Common Lisp

<lang lisp>(defun strip-chars (str chars)

 (remove-if (lambda (ch) (find ch chars)) str))

(strip-chars "She was a soul stripper. She took my heart!" "aei")

=> "Sh ws soul strppr. Sh took my hrt!"

</lang>

D

<lang d>import std.stdio, std.string;

void main() {

   auto s = "She was a soul stripper. She took my heart!";
   auto ss = "Sh ws  soul strppr. Sh took my hrt!";
   assert(s.removechars("aei") == ss);

}</lang>

Delphi

<lang Delphi>program StripCharacters;

{$APPTYPE CONSOLE}

uses SysUtils;

function StripChars(const aSrc, aCharsToStrip: string): string; var

 c: Char;

begin

 Result := aSrc;
 for c in aCharsToStrip do
   Result := StringReplace(Result, c, , [rfReplaceAll, rfIgnoreCase]);

end;

const

 TEST_STRING = 'She was a soul stripper. She took my heart!';

begin

 Writeln(TEST_STRING);
 Writeln(StripChars(TEST_STRING, 'aei'));

end.</lang>

Fortran

<lang Fortran>elemental subroutine strip(string,set)

 character(len=*), intent(inout) :: string
 character(len=*), intent(in)    :: set
 integer                         :: old, new, stride
 old = 1; new = 1
 do
   stride = scan( string( old : ), set )
   if ( stride > 0 ) then
     string( new : new+stride-2 ) = string( old : old+stride-2 )
     old = old+stride
     new = new+stride-1
   else
     string( new : ) = string( old : )
     return
   end if
 end do

end subroutine strip</lang>Note: Since strip is an elemental subroutine, it can be called with arrays of strings as well.

Go

<lang go>package main

import (

   "fmt"
   "strings"

)

func stripchars(str, chr string) string {

   return strings.Map(func(r rune) rune {
       if strings.IndexRune(chr, r) < 0 {
           return r
       }
       return -1
   }, str)

}

func main() {

   fmt.Println(stripchars("She was a soul stripper. She took my heart!",
       "aei"))

}</lang> Output:

Sh ws  soul strppr. Sh took my hrt!

Groovy

Solution: <lang groovy>def stripChars = { string, stripChars ->

   def list = string as List
   list.removeAll(stripChars as List)
   list.join()

}</lang>

Test: <lang groovy>println (stripChars('She was a soul stripper. She took my heart!', 'aei'))</lang>

Output:

Sh ws  soul strppr. Sh took my hrt!

Haskell

I decided to make the string the second argument and the characters the first argument, because it is more likely for someone to partially apply the characters to be stripped (making a function that strips certain characters), than the string. <lang haskell>stripChars :: String -> String -> String stripChars = filter . flip notElem</lang>

testing in GHCI:

> stripChars "aei" "She was a soul stripper. She took my heart!"
"Sh ws  soul strppr. Sh took my hrt!"

Icon and Unicon

The following works in both languages: <lang unicon>procedure main(A)

   cs := \A[1] | 'aei'   # argument is set of characters to strip
   every write(stripChars(!&input, cs))  # strip all input lines

end

procedure stripChars(s,cs)

   ns := ""
   s ? while ns ||:= (not pos(0), tab(upto(cs)|0)) do tab(many(cs)))
   return ns

end</lang>

Sample runs:

->strip
She was a soul stripper. She took my heart!
Sh ws  soul strppr. Sh took my hrt!
Aardvarks are ant eaters.
Ardvrks r nt trs.
->strip AEIOUaeiou
Aardvarks are ant eaters.
rdvrks r nt trs.
->

J

Solution:
The dyadic primitive -. (Less) is probably the simplest way to solve this task.

Example Usage: <lang j> 'She was a soul stripper. She took my heart!' -. 'aei' Sh ws soul strppr. Sh took my hrt!</lang>

Java

<lang Java>class StripChars {

   public static String stripChars(String inString, String toStrip) {
       return inString.replaceAll("[" + toStrip + "]", "");
   }
   public static void main(String[] args) {
       String sentence = "She was a soul stripper. She took my heart!";
       String chars = "aei";
       System.out.println("sentence: " + sentence);
       System.out.println("to strip: " + chars);
       System.out.println("stripped: " + stripChars(sentence, chars));
   }

}</lang>

output:

sentence: She was a soul stripper. She took my heart!
to strip: aei
stripped: Sh ws  soul strppr. Sh took my hrt!

JavaScript

<lang JavaScript>function stripchars(string, chars) {

 return string.replace(RegExp('['+chars+']','g'), );

}</lang>

<lang logo>to strip :string :chars

 output filter [not substringp ? :chars] :string

end

print strip "She\ was\ a\ soul\ stripper.\ She\ took\ my\ heart! "aei

bye</lang>

output:

Sh ws  soul strppr. Sh took my hrt!

Lua

<lang lua>function stripchars( str, chr )

   local s = ""
   for g in str:gmatch( "[^"..chr.."]" ) do
	s = s .. g
   end
   return s

end

print( stripchars( "She was a soul stripper. She took my heart!", "aei" ) )</lang>

Liberty BASIC

<lang lb> Print stripchars$("She was a soul stripper. She took my heart!", "aei", 1) End

Function stripchars$(strip$, chars$, num)

   For i = 1 To Len(strip$)
       If Mid$(strip$, i, 1) <> Mid$(chars$, num, 1) Then
           stripchars$ = (stripchars$ + Mid$(strip$, i, 1))
       End If
   Next i
   If (num <= Len(chars$)) Then stripchars$ = stripchars$(stripchars$, chars$, (num + 1))

End Function

</lang>

Mathematica

<lang Mathematica>stripchars[a_,b_]:=StringReplace[a,(#->"")&/@Characters[b]] stripchars["She was a soul stripper. She took my heart!","aei"] ->Sh ws soul strppr. Sh took my hrt!</lang>

MATLAB / Octave

<lang MATLAB> function str = stripchars(str, charlist)

   charlist = unique(charlist); 
   for k=1:length(charlist)
     str(str==charlist(k)) = []; 
   end; 
 end; </lang>
 >>stripchars('She was a soul stripper. She took my heart!','aei')
ans = Sh ws  soul strppr. Sh took my hrt!

Nemerle

<lang Nemerle>StripChars( text : string, remove : string ) : string {

   def chuck = Explode(remove);
   Concat( "", Split(text, chuck))

}</lang>

NetRexx

<lang NetRexx>/* NetRexx */

options replace format comments java crossref savelog symbols

say stripchars("She was a soul stripper. She took my heart!", "aei")

return

method stripchars(haystack, chs) public static

 loop c_ = 1 to chs.length
   needle = chs.substr(c_, 1)
   haystack = haystack.changestr(needle, )
   end c_
 return haystack

</lang>

Objective-C

Works with: Mac OS X version 10.5+
Works with: iOS version 1.0

<lang objc>@interface NSString (StripCharacters) - (NSString *) stripCharactersInSet: (NSCharacterSet *) chars; @end

@implementation NSString (StripCharacters) - (NSString *) stripCharactersInSet: (NSCharacterSet *) chars {

   return [[self componentsSeparatedByCharactersInSet:chars] componentsJoinedByString:@""];

} @end</lang>

To use: <lang objc> NSString *aString = @"She was a soul stripper. She took my heart!";

   NSCharacterSet* chars = [NSCharacterSet characterSetWithCharactersInString:@"aei"];
   // Display the NSString.
   NSLog(@"%@", [aString stripCharactersInSet:chars]);</lang>

OCaml

<lang ocaml>let stripchars s cs =

 let len = String.length s in
 let res = String.create len in
 let rec aux i j =
   if i >= len then String.sub res 0 j
   else if String.contains cs s.[i] then
     aux (succ i) (j)
   else begin
     res.[j] <- s.[i];
     aux (succ i) (succ j)
   end
 in
 aux 0 0</lang>

testing in the toplevel:

# stripchars "She was a soul stripper. She took my heart!" "aei" ;;
- : string = "Sh ws  soul strppr. Sh took my hrt!"

PARI/GP

GP should not be used for string manipulation. A good solution to this problem would probably involve system("perl -e... <lang parigp>stripchars(s, bad)={

 bad=Set(Vec(Vecsmall(bad)));
 s=Vecsmall(s);
 my(v=[]);
 for(i=1,#s,if(!setsearch(bad,s[i]),v=concat(v,s[i])));
 Strchr(v)

}; stripchars("She was a soul stripper. She took my heart!","aei")</lang>

Pascal

See Delphi

Perl

Note: this example uses a regular expression character class. Certain characters, like hyphens and brackets, may need to be escaped. <lang perl>sub stripchars {

   my ($s, $chars) = @_;
   $s =~ s/[$chars]//g;
   return $s;

}

print stripchars("She was a soul stripper. She took my heart!", "aei"), "\n";</lang> Output:

Sh ws  soul strppr. Sh took my hrt!

Another good option for stripping characters is to use the tr/// operator. This option is very efficient when the set of characters to strip is fixed at compile time, because tr/// is specifically designed for transforming and deleting characters. Note that hyphens also have special meaning in this case. <lang perl>$str =~ tr/aei//d;</lang>

Since the characters used for tr/// must be fixed at compile time, unfortunately, it requires the use of an eval to do this generally for any set of characters provided at runtime: <lang perl>sub stripchars {

   my ($s, $chars) = @_;
   eval("\$s =~ tr/$chars//d;");
   return $s;

}</lang>

Perl 6

<lang perl6>sub strip_chars ( $s, $chars ) {

   return $s.trans( $chars.comb X=>  );

}

say strip_chars( 'She was a soul stripper. She took my heart!', 'aei' );</lang>

Output:

Sh ws  soul strppr. Sh took my hrt!

PHP

<lang php><?php function stripchars($s, $chars) {

   return str_replace(str_split($chars), "", $s);

}

echo stripchars("She was a soul stripper. She took my heart!", "aei"), "\n"; ?></lang> Output:

Sh ws  soul strppr. Sh took my hrt!

PicoLisp

<lang PicoLisp>(de strDiff (Str1 Str2)

  (pack (diff (chop Str1) (chop Str2))) )</lang>

Output:

: (strDiff "She was a soul stripper. She took my heart!" "aei")
-> "Sh ws  soul strppr. Sh took my hrt!"

PL/I

<lang PL/I> strip_chars: procedure (text, chars) returns (character (100) varying);

  declare text character (*) varying, chars character (*) varying;
  declare out_text character (100);
  declare ch character (1);
  declare (i, j) fixed binary;
  j = 0;
  do i = 1 to length(text);
     ch = substr(text, i, 1);
     if index(chars, ch) = 0 then
        do; j = j + 1; substr(out_text, j, 1) = ch; end;
  end;
  return (substr(out_text, 1, j) );

end strip_chars; </lang>

PureBasic

PureBasic uses a single (for ASCII) or a two-byte (for Unicode) null to signal the end of a string. Nulls are thus excluded from the allowable characters to strip as they can't be included in a PureBasic string. <lang PureBasic>Procedure.s stripChars(source.s, charsToStrip.s)

 Protected i, *ptrChar.Character, length = Len(source), result.s
 *ptrChar = @source
 For i = 1 To length
   If Not FindString(charsToStrip, Chr(*ptrChar\c))
     result + Chr(*ptrChar\c)
   EndIf
   *ptrChar + SizeOf(Character)
 Next
 ProcedureReturn result 

EndProcedure

If OpenConsole()

 PrintN(stripChars("She was a soul stripper. She took my heart!", "aei"))
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
 CloseConsole()

EndIf</lang> Sample output:

Sh ws  soul strppr. Sh took my hrt!

Python

Not using regular expressions

Works with: Python version 2.6+

<lang python>>>> def stripchars(s, chars): ... return s.translate(None, chars) ... >>> stripchars("She was a soul stripper. She took my heart!", "aei") 'Sh ws soul strppr. Sh took my hrt!'</lang>

Works with: Python version 2.x

<lang python>>>> import string >>> def stripchars(s, chars): ... return s.translate(string.maketrans("", ""), chars) ... >>> stripchars("She was a soul stripper. She took my heart!", "aei") 'Sh ws soul strppr. Sh took my hrt!'</lang>

Implemented manually: <lang python>>>> def stripchars(s, chars): ... return "".join(c for c in s if c not in chars) ... >>> stripchars("She was a soul stripper. She took my heart!", "aei") 'Sh ws soul strppr. Sh took my hrt!'</lang>

Using regular expressions

<lang python>>>> import re >>> def stripchars(s, chars): return re.sub('[%s]+' % re.escape(chars), , s)

>>> stripchars("She was a soul stripper. She took my heart!", "aei") 'Sh ws soul strppr. Sh took my hrt!' >>> </lang>

REXX

<lang REXX>/* Rexx */

Do

 Say stripchars("She was a soul stripper. She took my heart!", "aei")
 Return

End Exit

stripchars:

 Procedure

Do

 Parse arg haystack, chs
 Do c_ = 1 to length(chs)
   needle = substr(chs, c_, 1)
   haystack = changestr(needle, haystack, )
   End c_
 Return haystack

End Exit </lang>

Ruby

<lang ruby>>> "She was a soul stripper. She took my heart!".delete("aei") => "Sh ws soul strppr. Sh took my hrt!"</lang>

Scala

<lang scala>def stripChars(s:String, ch:String)= s filterNot (ch contains _)

stripChars("She was a soul stripper. She took my heart!", "aei") // => Sh ws soul strppr. Sh took my hrt!</lang>

Sed

Using echo and piping it through a sed filter: <lang bash>#!/bin/bash

strip_char() {

 echo "$1" | sed "s/[$2]//g"

}

</lang>

Seed7

<lang seed7>$ include "seed7_05.s7i";

const func string: stripchars (in string: mainStri, in string: charList) is func

 result
   var string: strippedStri is "";
 local
   var char: ch is ' ';
 begin
   strippedStri := mainStri;
   for ch range charList do
     strippedStri := replace(strippedStri, str(ch), "");
   end for;
 end func;

const proc: main is func

 begin
   writeln(stripchars("She was a soul stripper. She took my heart!", "aei"));
 end func;</lang>

Output:

Sh ws  soul strppr. Sh took my hrt!

Standard ML

<lang sml>fun stripchars (string, chars) = let

 fun aux c =
   if String.isSubstring (str c) chars then
     ""
   else
     str c

in

 String.translate aux string

end</lang>

testing in the interpreter:

- stripchars ("She was a soul stripper. She took my heart!", "aei") ;
val it = "Sh ws  soul strppr. Sh took my hrt!" : string

Alternately: <lang sml>fun stripchars (string, chars) =

 String.concat (String.tokens (fn c => String.isSubstring (str c) chars) string)

</lang>

testing in the interpreter:

- stripchars ("She was a soul stripper. She took my heart!", "aei") ;
val it = "Sh ws  soul strppr. Sh took my hrt!" : string

Smalltalk

Works with: Pharo version 1.3-13315

<lang smalltalk> | stripChars | stripChars := [ :string :chars | string reject: [ :c | chars includes: c ] ]. stripChars value: 'She was a soul stripper. She took my heart!' value: 'aei'.

"'Sh ws soul strppr. Sh took my hrt!'" </lang>

Tcl

<lang tcl>proc stripchars {str chars} {

   foreach c [split $chars ""] {set str [string map [list $c ""] $str]}
   return $str

}

set s "She was a soul stripper. She took my heart!" puts [stripchars $s "aei"]</lang>

UNIX Shell

One would normally do this using the standard tr(1) command:

Works with: sh

<lang bash>strip_chars() {

 echo "$1" | tr -d "$2"

}</lang>

But it can also be accomplished with bash's built-in parameter expansions:

Works with: bash

<lang bash>function strip_chars {

 echo "${1//[$2]}"

}</lang>

Test code:

<lang bash> strip_chars "She was a soul stripper. She took my heart!" aei</lang>

Output:

Sh ws  soul strppr.  Sh took my hrt!

TXR

This solution uses the functions compl-span-str and span-str, which are based directly on the standard C library functions strspn and strcspn (or, rather, their wchar_t counterparts wcsspn and wcscspn).

<lang txr>@(next :args) @arg1 @arg2 @(do (defun strip-chars (str set)

      (for ((pieces ()) (str-suffix str))
           ((not (zerop (length str-suffix))) (cat-str (nreverse pieces) ""))
           ()
        (let* ((len-piece (compl-span-str str-suffix set))
               (piece (sub-str str-suffix 0 len-piece))
               (suff0 (sub-str str-suffix len-piece nil))
               (len-non-piece (span-str suff0 set)))
          (push piece pieces)
          (set str-suffix (sub-str suff0 len-non-piece nil))))))

@(bind result @(strip-chars arg1 arg2))</lang>

$ ./txr rosetta/strip-chars.txr "she was a soul stripper. she stole my heart." "aei"
arg1="she was a soul stripper. she stole my heart."
arg2="aei"
result="sh ws  soul strppr. sh stol my hrt."

Ursala

Normally there's no need to define this operation because it's built in. <lang Ursala>strip = ~&j

  1. cast %s

test = strip('she was a soul stripper. she took my heart','aei')</lang> output:

'sh ws  soul strppr. sh took my hrt'