Remove characters from a string

February 24, 2012

We will write three versions of the function. The first uses classic lisp-style recursion down the cdrs of a list:

; lisp-style recursion down the cdrs of a list
(define (string-remove str match)
  (let loop ((ss (string->list str)) (zs (list)))
    (cond ((null? ss) (list->string (reverse zs)))
          ((string-index (car ss) match) (loop (cdr ss) zs))
          (else (loop (cdr ss) (cons (car ss) zs))))))

That works, but it seems inefficient to convert to and from lists, and the list manipulations create a lot of garbage. The typical approach used in C programs is to walk the string using pointers:

; c-style walk the string using pointers
(define (string-remove str match)
  (let loop ((src 0) (dest 0))
    (cond ((= (string-length str) src)
            (substring str 0 dest))
          ((string-index (string-ref str src) match)
            (loop (+ src 1) dest))
          (else (string-set! str dest (string-ref str src))
                (loop (+ src 1) (+ dest 1))))))

Since that manipulates the string in place, there is no garbage, and the function is much faster; that’s the version I wrote during the development of my program. A third version uses combinators in the style of Haskell:

; haskell-style using combinators
(define (string-remove str match)
  (list->string
    (filter
      (complement (right-section string-index match))
      (string->list str))))

That’s actually clearer in Haskell, which represents strings natively as lists of characters, eliminating the need to convert back and forth.

We used string-index, complement and right-section from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/dL1Uy4sR. Be aware that MzScheme, which is used at codepad, make strings immutable by default, so the C-style version that operates in-place requires special handling to make the input string mutable. Mutable strings are standard in R5RS; immutable strings are standard in R6RS.

Pages: 1 2

27 Responses to “Remove characters from a string”

  1. […] today’s Programming Praxis exercise, our task is to remove all the characters in one string from the other. […]

  2. My Haskell solution (see http://bonsaicode.wordpress.com/2012/02/24/programming-praxis-remove-characters-from-a-string/ for a version with comments):

    remove :: Eq a => [a] -> [a] -> [a]
    remove = filter . flip notElem
    
  3. Steve Massey said

    Clojure:

    (fn [s cs] (apply str (remove (set cs) s)))

  4. Paul G. said

    Perl’s substitution operator (http://perldoc.perl.org/functions/s.html) was intended for just such text manipulation. Here is a one liner which can be run from command line

    perl -e '$q = "Programming Praxis"; $q =~ s/[aeiou]//g; print $q'
    
  5. Jussi Piitulainen said

    In a Scheme-like language with string ports one could also write the desired characters into a string port and in the end extract the accumulated string, something like the following (I’m making up the procedure names, but I bet these things can be found in Racket, for example, and I think they will be in R7RS). Java’s StringBuilder is similar.

    (define (string-minus s x)
      (let ((p (make-string-port)))
        (string-for-each
         (lambda (c) (if (not (string-find c s)) (write-char c p)))
         s)
        (port-string p)))
    
  6. Jussi Piitulainen said

    And of course I made a silliest typo. Should be (string-find c x).

  7. rlonstein said

    Very short in Python:

      import string
      def remove_str(s,r):
          return s.translate(None,r)
    

    In Common Lisp, it’s a one-liner…

    (defun remove-str (s1 s2) (remove-if #'(lambda (c) (position c s2)) s1))

    or destructively…

    (defun delete-str (s1 s2) (delete-if #'(lambda (c) (position c s2)) s1))

  8. Lautaro Pecile said
    def remove_chars(s, r):
        return ''.join([c for c in s if not c in r])
    
  9. Jussi Piitulainen said

    This is an actual string-port-using Scheme procedure, tested with Chibi.
    (It relies on the new letrec* semantics of internal defines.)

    (define (string-remove s r)
      (define t (open-output-string))
      (define x (string->list r))
      (define (p c) (if (not (memv c x)) (write-char c t)))
      (for-each p (string->list s))
      (get-output-string t))
    
  10. Manoj Senguttuvan said

    PHP CLI Code:

    <? echo str_replace(str_split($argv[2]),'',$argv[1]); ?>
    

    or the C Code:

    int main(int argc,char* argv[])
    {
            int i=0,j,flag=0;
            for(;i<strlen(argv[1]);i++)
            {
                    for(j=0;j<strlen(argv[2]);j++)
                            flag=argv[1][i]==argv[2][j]?1:flag;
                    printf("%c",flag--!=1?argv[1][i]:0);
            }
    }
    
  11. […] are many answers to today’s exercise on Programming Praxis which is to remove from a string characters given in another string. I liked […]

  12. shiro said

    Scheme already has the feature in srfi-13 (and srfi-14 for the convenience). Is it cheating?

    (string-delete “Programming Praxis” (->char-set “aeiou”)) => “Prgmmng Prxs”

  13. Nick said

    //Method in Java

    public String removeChars(String str1,String str2)
    {
    String temp=””;
    int len = str2.length();
    for(int i=0;i<len;i++)
    {
    for(int j=0;j“Prgrmmng Prxs
    //removeChars(“how do i sound without vowels”,”aeiou”)==>hw d snd wtht vwls

  14. Nick said
    public  String removeChars(String str1,String str2) 
    	{
    		String temp="";
    		int len = str2.length();
    		for(int i=0;i<len;i++)
    		{
    			for(int j=0;j<str1.length();j++)
    			{
    				if(str1.charAt(j)==str2.charAt(i))
    				   continue;
    				else
    				   temp = temp + str1.charAt(j);
    			}
    			str1=temp;
    			temp="";
    		}
    		return str1;
    	}
    
  15. Nick said

    above method written in java

  16. Axio said
    (define (string-remove str1 str2)
      (let ((l1 (string->list str1))
            (l2 (string->list str2)))
        (with-output-to-string ""
          (lambda ()
            (for-each
              (lambda (c)
                (unless (memv c l2) (display c)) )
              l1)))))
    

    Of course, we’d prefer a better data structure for l2, like a map, for faster access…

  17. Nelson said

    public static String remove(String in1, String in2) {
    if (in1 == null || in2 == null) {
    return “”;
    }
    boolean[] bits = new boolean[256];
    char[] chares2 = in2.toCharArray();
    for (int i = 0; i < chares2.length; i++) {
    bits[chares2[i]] = true;
    }
    char[] chares1 = in1.toCharArray();
    for (int j = 0; j < chares1.length; j++) {
    if (bits[chares1[j]]) {
    chares1[j] = 0;
    }
    }
    return new String(chares1);
    }

  18. Nelson said

    Java version


    public static String remove(String in1, String in2) {
    if (in1 == null || in2 == null) {
    return "";
    }
    boolean[] bits = new boolean[256];
    char[] chares2 = in2.toCharArray();
    for (int i = 0; i < chares2.length; i++) {
    bits[chares2[i]] = true;
    }
    char[] chares1 = in1.toCharArray();
    for (int j = 0; j < chares1.length; j++) {
    if (bits[chares1[j]]) {
    chares1[j] = 0;
    }
    }
    return new String(chares1);
    }

  19. Here’s some simple Javascript code that completes the task:

    var removeCharacters = function(first, second){
        var solution = "";
        for(var i = 0; i < first.length; i++){
            if(second.indexOf(first[i]) >= 0)
                continue;
            solution += first[i];
        }
        return solution;
    };
    
    console.log(removeCharacters("Programming Praxis", "aeiou"));
    console.log(removeCharacters("Programming Praxis", "P"));
    console.log(removeCharacters("Programming Praxis", "ra"));
    
  20. Mike said

    Slightly more general purpose function that works on any iterable:

    
    from itertools import ifilterfalse
    
    def elide(iterable, remove):
        """filters objects from 'iterable' that are in 'remove'.
    
        examples:
        >>> ''.join(filter_chars("Programming Praxis", "aeiou"))
        'Prgrmmng Prxs'
    
        >>> list(filter_chars(range(10), [1,3,5,7,9]))
        [0, 2, 4, 6, 8]
        """
        
        return ifilterfalse(remove.__contains__, iterable)
    
    
  21. Prashant said

    void remove_from_string(string source, string pattern, string& result){
    for(unsigned int i = 0; i != source.length(); i++){
    char ch = source.at(i);
    int pos = pattern.find(ch);
    if(pos == -1){
    result.push_back(ch);
    }
    }
    }

  22. paul said
    #!/usr/bin/python
    
    def parser(st):
        k = range(len(st))
        for i in range(len(st)):
            k[i] = st[i]
        return k
    
    def intersect(x,y):
        x, y = parser(x), parser(y)
    
        for i in y:
            if i in x and i != ' ':
                while i in x:
                    x.remove(i)
        return ''.join(x)
    
    
  23. Anooj said

    string s1 = “Programming Praxis”;
    string s2 = “aeiou”;
    foreach (char c in s2)
    {
    s1 = s1.Replace(c, ‘ ‘).Replace(” “,””);
    }

  24. Ankit Thakur said

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.ArrayList;

    public class Remove {
    ArrayList characterlist=new ArrayList();
    public void problem()
    {
    try
    {
    System.out.println(“Enter the first sentence”);
    BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
    String word1=br.readLine();
    System.out.println(“Enter the second sentence/word”);
    String word2=br.readLine();
    for(int count=0;count<word2.length();count++)
    {
    if(!present(word2.charAt(count)))
    {
    characterlist.add(word2.charAt(count));
    }
    }
    int counter=0;
    while(counter<word1.length())
    {
    if(present(word1.charAt(counter)))
    {
    if(counter==0)
    word1=word1.substring(counter+1);
    else
    {
    word1=word1.substring(0,counter)+word1.substring(counter+1);
    }
    counter–;
    }
    counter++;
    }
    System.out.println(word1);
    }
    catch(IOException ioe)
    {
    ioe.printStackTrace();
    }
    }
    public boolean present(char ch)
    {
    for(char c:characterlist)
    {
    if(ch==c)
    return true;
    }
    return false;
    }
    }

  25. In python:

    # Python program to remove the charachter
    # given in second string
    # The program will take two string as input
    # Objective is to remove the charachters from the first string
    # which is determined by second string

    def Remove_String(Original_Str, Rem_Chr):

    for j in Rem_Chr:

    if Original_Str.find(j)!= -1:

    Original_Str = Original_Str.replace(j,”)

    print(Original_Str)

    Remove_String(‘Programming Praxis’, ‘aeiou’)

  26. In Python:

    # Python program to remove the charachter
    # given in second string
    # The program will take two string as input
    # Objective is to remove the charachters from the first string
    # which is determined by second string
    
    def Remove_String(Original_Str, Rem_Chr):	
    	
    	for j in Rem_Chr:
    	
    		if Original_Str.find(j)!= -1:
    			
    			Original_Str = Original_Str.replace(j,'')
    				
    	print(Original_Str)
    					
    			
    				
    Remove_String('Programming Praxis', 'aeiou')
    
    
  27. Kevin said

    Solution in java

    public class RemoveFromStr
    {  
      public static void main(String[] args){
        System.out.println(removeFromStr("i rule !","iue"));
      }
      
      public static String removeFromStr(String x, String y)
      {
        String res = "";
        for(int i = 0; i < x.length(); i++)
          res += (y.indexOf(x.charAt(i))==-1) ? x.charAt(i) : "";
        return res;      
      }  
    }
    

Leave a comment