Home > Mobile >  Best way to remove characters at certain positions in a Java string or stringbuilder
Best way to remove characters at certain positions in a Java string or stringbuilder

Time:04-12

process_str(StringBuilder copy, List<Integer> idxList) {
        for(int i = 0; i < idxList.size();   i) {
            int pos  = idxList.get(i);
            copy.setCharAt(pos, '$');
        }
        StringBuilder output = new StringBuilder();
        for(int i = 0; i < copy.length();   i) {
            char ch = copy.charAt(i);
            if(ch != '$')
                output.append(ch);
        }
        return output.toString();
}

Constraint - $ does not appear in the input string. Is there a simpler way to do this?

CodePudding user response:

You can remove the first loop like this:

process_str(StringBuilder copy, List<Integer> idxList) {
    StringBuilder output = new StringBuilder();
    for(int i = 0; i < copy.length();   i) {
        char ch = copy.charAt(i);
        if (idxList.contains(i))
            output.append(ch);
    }
    return output.toString();
}

The overall time complexity might be different depending on what type of List you use.

CodePudding user response:

I've read that your solution has a constraint where the original string does not contain a dollar sign, but you could keep your code more generalized if you don't impose said constraint.

If your goal is to keep it as concise as possible you could use streams, strictly a sequential stream, with a stateful lambda:

        String str = "Hello my new world!";
        List<Integer> idxList = new ArrayList<>(List.of(3, 5, 6));
        StringBuilder strBld = new StringBuilder();

        IntStream.range(0, str.length()).boxed().forEach(i -> {
            if (!idxList.contains(i)) strBld.append(str.charAt(i));
        });

CodePudding user response:

Solution similar to rikyeah but avoiding the complexity of contains. Here we first sort the input idxList in order to have the indices in ascendant order, then we create the output StringBuilder with a initial capacity computed from the length of the input StringBuilder and the number of index to remove. Finally we browse the input StringBuilder and avoid the copy when we reach the next index to remove.

public String process_str(StringBuilder copy, List<Integer> idxList) {
    List<Integer> sortedIndices = new ArrayList<>(idxList);
    Collections.sort(sortedIndices);
    Iterator<Integer> idxIterator = sortedIndices.iterator();
    int currIdx;
    if (idxIterator.hasNext()) {
        currIdx = idxIterator.next();
    } else {
        currIdx = copy.length();
    }
    StringBuilder output = new StringBuilder(copy.length() - idxList.size());
    for(int i = 0; i < copy.length();   i) {
        char ch = copy.charAt(i);
        if (i != currIdx) {
            output.append(ch);
        } else if (idxIterator.hasNext()) {
            currIdx = idxIterator.next();
        }
    }
    return output.toString();
}
  •  Tags:  
  • java
  • Related