Khushi
Khushi

Reputation: 333

remove comma and some characters from a string

I have a string that can be in any of the format like below:

'xyz','abc'         //after conversion --> 'abc'
'abc','xyz'         //after conversion --> 'abc'  
'xyz'               //after conversion --> 
'abc','xyz','abc'   //after conversion --> 'abc','abc'

In this I have to remove 'xyz' and if it has any leading or trailing comma. Please suggest how can I achieve this with regular expression.

Thanks

Upvotes: 0

Views: 739

Answers (2)

VLAZ
VLAZ

Reputation: 28977

Regex alone is not very well equipped for this task. However, you can do the following:

  1. Split your string on comma. In fact, you can split by comma surrounded by any amount of whitespace, in case the sting you get is "'abc', 'xyz'", for example. You can use the regex \s*,\s* for that.
  2. Remove anything that matches the string you don't want - you can use basic string matching or regex for more complex patterns.
  3. Convert the split string into a comma separated list again.

Usign Java 8 Stream operations, this can be short:

String[] split = str.split(("\\s*,\\s*")); //1. split into separate strings
String result = Arrays.stream(split) //turn to stream
        .filter(chunk -> !"'xyz'".equals(chunk)) //2. remove anything you don't want
        .collect(Collectors.joining(",")); //3. convert back to comma separated list

The .filter predicate can be changed to whatever suits you - if you only want to match "'abc'" then you can use chunk -> "abc'".equals(chunk) or you can use .contains or equalsIgnoreCase, or even regex.


It might be worth extracting the filter rule out into a separate Predicate, so you can more easily change it, when needed

Predicate<String> filterRule = chunk -> !"'xyz'".equals(chunk);

/* ... */
  .filter(filterRule)
/* ... */

Although if we examine this "'xyz'".equals is already a predicate itself, and predicates can be negated, so you don't need to write a whole lambda for this but just re-use the methods as functional interfaces:

Predicate<String> stuffWeDontWant = "'xyz'"::equals;
Predicate<String> filterRule = stuffWeDontWant.negate();

This can all be inlined but it's a bit ugly, as you have to cast it into the proper predicate to negate it

Predicate<String> filterRule = ((Predicate<String>) "'xyz'"::equals).negate();

The final thing can look like this:

Predicate<String> filterRule = ((Predicate<String>) "'xyz'"::equals).negate();

String result = Arrays.stream(str.split(("\\s*,\\s*")))
    .filter(filterRule)
    .collect(Collectors.joining(","));

So now you can more easily change whatever your filter rule is. You can even re-use this for any kind of list by just passing different predicate to use as a filter.


A non-Java 8 or non-Stream way to do the same to do the following:

String[] split = str.split(("\\s*,\\s*")); //1. split into separate strings

List<String> list = new ArrayList<>(Arrays.asList(split));//convert into an ArrayList to allow removing

list.removeAll(Collections.singleton("'xyz'"));//2. remove anything you don't want
String result = String.join(",", list); //3. convert back to comma separated list

This approach can still be mixed with using a Predicate by using .removeIf() but this time it has to match exactly what you don't want:

list.removeIf("'xyz'"::equals);
/* or */
list.removeIf("'xyz'"::equalsIgnoreCase);
/* or */
list.removeIf("'xyz'"::startsWith);
/* or */
list.removeIf("'xyz'"::contains);
/* or */
list.removeIf("'xyz'"::endsWith);
/* or */
list.removeIf(Pattern.compile("'(xy?z)*'").asPredicate());
/* ...and so on... */

Upvotes: 0

Scary Wombat
Scary Wombat

Reputation: 44824

You could chain some String::replace methods

String str = "'abc','xyz','abc'";
str = str.replace (",'xyz'", "").replace("'xyz',", "").replace("'xyz'", "");

output

'abc','abc'

Upvotes: 1

Related Questions