Strip a set of characters from a string: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added JavaScript example)
(→‎{{header|AWK}}: stripchar)
Line 70: Line 70:
Output:
Output:
<pre>Sh ws soul strppr. Sh took my hrt!</pre>
<pre>Sh ws soul strppr. Sh took my hrt!</pre>

=={{header|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:
<pre>She was a soul stripper. She took my heart!
Sh ws soul strppr. Sh took my hrt!
</pre>


=={{header|BASIC}}==
=={{header|BASIC}}==

Revision as of 18:17, 3 February 2012

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

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!

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

<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'