Home > Net >  Removing a string of letters from a String Java
Removing a string of letters from a String Java

Time:04-03

Okay been on this for a while now and have gone through many different versions of doing this the goal is to have a method like remove("pdi") and it will return "eter er cke"

public class CodioCustomString {

public static void main(String[] args) {
    System.out.println(remove("pdi"));
    
}

//2 Variables
static String myString = "peter piper picked";
boolean isSet;

//constructor

public static String remove(String arg) {
    char[] chars = arg.toCharArray();
    StringBuilder newString = new StringBuilder(myString);
    for(char i: chars) {
        for(int k = 0; k < myString.length(); k  ) {
            if(i == myString.charAt(k)) {
                newString.deleteCharAt(k);
                continue;
            }
            else {
                continue;
            }

        }
        
        }
    return newString.toString();
}

CodePudding user response:

Here are three methods to do it. The methods take two argument.

  • the target string subject to removal
  • the source string of characters to be removed.
String result1 = remove1("peter piper picked", "pbi");
System.out.println(result1);

String result2 = remove2("peter piper picked", "pbi");
System.out.println(result2);

String result3 = remove3("peter piper picked", "pbi");
System.out.println(result3);

prints

eter er cked
eter er cked
eter er cked

Explanations

remove1

The easiest way is as follows:

  • use replaceAll which takes a regular expression
  • [abc] is a character class which matches any of those characters. So simply create one by surrounding your letters to be removed with brackets.
  • replace the occurrence of those characters with an empty string.
public static String remove1(String target, String toBeRemoved) {
    return target.replaceAll("["   toBeRemoved   "]", "");
}

remove2

If you prefer to do it in a loop you can do the following:

  • simply iterate across the characters of the string.
  • if the removal letters contains the character, ignore it.
  • else append it to a StringBuilder
public static String remove2(String target, String toBeRemoved) {
    StringBuilder sb = new StringBuilder();
    for (char ch : target.toCharArray()) {
        if (!toBeRemoved.contains(Character.toString(ch))) {
            sb.append(ch);
        }
    }
    return sb.toString();
}

remove3

This method streams the characters.

  • map each character to a string
  • filter out the ones to be removed
  • collect into a new String using Collectors.joining()
public static String remove3(String target, String toBeRemoved) {
    return target.chars().mapToObj(Character::toString)
            .filter(s->!toBeRemoved.contains(s))
            .collect(Collectors.joining());
}
    

CodePudding user response:

The problem is that you are comparing the length of myString in the for loop which is fixed. Instead you should be comparing it with the length of StringBuilder ( newString in this case) as you are reducing the length when performing the delete operation.

Also, the time complexity (t.c) of the above code is O(n*k) where n is the length of the string and k the length of string that needs to be removed.

You can improve the time complexity by storing the character in a set and then iterating the newString and performing the remove operation.

public class CodioCustomString {
    public static void main(String[] args) {
        System.out.println(remove("pdi"));
        System.out.println(remove2("pdi"));
    }

    // 2 Variables
    static String myString = "peter piper picked";
    boolean isSet;

    /** tc - o(nk) where k is length of args string and n is length of string */
    private static String remove(String arg) {
        char[] chars = arg.toCharArray();
        StringBuilder newString = new StringBuilder(myString);
        for (char i : chars) {
            for (int k = 0; k < newString.length(); k  ) {
                if (i == newString.charAt(k)) {
                    newString.deleteCharAt(k);
                    k--;
                } else {
                    continue;
                }

            }

        }
        return newString.toString();
    }

    /**
     * tc - o(n)   o(k) where k is length of args string and n is length of string
     */
    private static String remove2(String arg) {
        char[] chars = arg.toCharArray();
        Set<Character> set = new HashSet<>();
        for (char i : chars) {
            set.add(i);
        }
        StringBuilder newString = new StringBuilder(myString);

        for (int k = 0; k < newString.length(); k  ) {
            if (set.contains(newString.charAt(k))) { // set.contains is o(1) operations
                newString.deleteCharAt(k);
                k--;
            }

        }

        return newString.toString();
    }
}

and the expected output :

eter er cke
eter er cke

CodePudding user response:

After the first delete in StringBuilder, it’s not consistent with myString. So, you are not exactly removing the same character you are referring in myString. To fix, iterate on newString instead of myString.


Better solution with lower time complexity:

import java.util.*;
import java.util.stream.*;

class Main {  
  static String myString = "peter piper picked";
  
  public static void main(String args[]) { 
    System.out.println(remove("pdi"));
  } 

  public static String remove(String arg) {
    Set<Character> set = arg.chars()
                            .mapToObj(c -> (char) c)
                            .collect(Collectors.toSet());

    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < myString.length(); i  ) {
      if (!set.contains(myString.charAt(i))) {
        sb.append(myString.charAt(i));
      }
    }

    /*
     OR: 
     myString.chars()
             .mapToObj(c -> (char) c)
             .filter(c -> !set.contains(c))
             .forEach(sb::append);
    */

    return sb.toString();
  }
}

Using a set for the argument String will save you one loop and the operation can be O(n) instead of O(nk).

  • Related