user2961454
user2961454

Reputation: 353

How to remove duplicate values in string which has delimiters

I have string with value as ||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||

I am trying to write code which should remove duplicates and return the unique values retaining the demiliters like this ||HelpDesk||IT Staff||Admin||Audit||

My code is using HashSet to remove duplicates but the problem is it is removing delimiters. How can I retain delimiters by removing duplicate values only.

Below is my code after removing duplicates and adding back delimiters. But not sure if there is easy way of doing this.

public static void main(String[] args) {
    TestDuplicates testDuplicates = new TestDuplicates();
    String bRole = "||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||";
    List<String> listWithoutDuplicates = new ArrayList<String>();
    String noDup = "";
    List<String> splittedStringList =
        new ArrayList<String>();
    SplitOperations splitOperations =
        new SplitOperations();
    splittedStringList =
            splitOperations.splitString(bRole);
    for (int i = 0; i < splittedStringList.size(); i++) {

        HashSet<String> listToSet = new HashSet<String>(splittedStringList);

        listWithoutDuplicates = new ArrayList<String>(listToSet);


    }
    for(int i=0;i<listWithoutDuplicates.size();i++){
         noDup = noDup + "||"+listWithoutDuplicates.get(i);
        System.out.println(listWithoutDuplicates.get(i));
    } 
    System.out.println("No Duplicate is::"+ noDup+"||");


}

Thanks

Upvotes: 1

Views: 3027

Answers (5)

Bohemian
Bohemian

Reputation: 425238

Here's a regex-based one liner:

str = str.replaceAll("(\\|[^|]+)(?=.*\\1\\|)", "");

This works by replacing every term that is followed by itself somewhere ahead via a look ahead assertion that uses a back reference.

Here's a non-regex java 8 one liner:

Arrays.stream(str.substring(1).split("[|]")).distinct().collect(Collectors.joining("|", "|", "|"));

Upvotes: 0

nitishagar
nitishagar

Reputation: 9413

Using Guava lib it's a one liner:

Joiner.on("||").skipNulls(Splitter.on("||").trimResults().split(<target_string>);)

Here is my attempt at it:

import java.util.*;

public class Seperator {
  public static void main(String[] args) {

    String bRole = "||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||";

    List<String> listWithoutDuplicates = new ArrayList<String>();

    String noDup = "";

    List<String> splittedStringList = new ArrayList<String>();

    splittedStringList = Arrays.asList(bRole.split("\\|\\|"));

    LinkedHashSet<String> listToSet = new LinkedHashSet<String>(splittedStringList);

    noDup = Seperator.join(listToSet, "||");

    System.out.println("No Duplicate is::"+ noDup+"||");
  }

  public static String join(Set<String> set, String sep) {
    String result = null;
    if(set != null) {
      StringBuilder sb = new StringBuilder();
      Iterator<String> it = set.iterator();
      if(it.hasNext()) {
        sb.append(it.next());
      }
      while(it.hasNext()) {
        sb.append(sep).append(it.next());
      }
      result = sb.toString();
    }
    return result;
  }
} 

LinkedHashSet are mainly used to preserve the order and ofcourse get uniques elements. Joining is pretty standard, but we can use Google's Guava Library also (Joiner):

So, instead of Seperator.join(listToSet, "||");

You'll have: Joiner.on("||").join(listToSet);

Upvotes: 0

Sariq Shaikh
Sariq Shaikh

Reputation: 1124

This should work, also it will maintain sequence of elements if you want. Note that I have not written code to put delimiters again.

public static void main(String s[]){

        String a = "||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||";
        a = a.replaceAll("\\|\\|",",");
        String arr[] = a.split(",");
        //linked hash set in case you want to maintain the sequence of elements
        Set<String> set = new LinkedHashSet<String>(Arrays.asList(arr));
        set.remove("");
        System.out.println(set);
        //Iterate through the set and put your delimiters here again
    }

Upvotes: 0

Alexis C.
Alexis C.

Reputation: 93872

You could use a LinkedHashSet to preserve insertion order. Once you splitted the String by "||" just add the delimiters when constructing back the String.

 String s = "||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||";
 Set<String> set = new LinkedHashSet<>(Arrays.asList(s.split(Pattern.quote("||"))));
 String noDup = "||";
 for(String st : set) {
     if(st.isEmpty()) continue;
     noDup += st+"||";
 }

Or using the new java 8 Stream API :

 String noDup = "||"+
     Arrays.stream(s.split(Pattern.quote("||")))
           .distinct()
           .filter(st -> !st.isEmpty()) //we need to remove the empty String produced by the split
           .collect(Collectors.joining("||"))+"||";

Both approaches yield the same result (||HelpDesk||IT Staff||Admin||Audit||).

Upvotes: 1

Emz
Emz

Reputation: 1280

public String removeDublicate () {
    String str = "||HelpDesk||IT Staff||IT Staff||Admin||Audit||HelpDesk||";
    String split[] = str.split("\\|\\|");

    String newStr = "";

    for (String s : split) {
        if (!s.isEmpty() && !newStr.contains(s)) {
            newStr += "||" + s;
        }
    }

    newStr += "||";

    return newStr;
}

Something like that? str could be an argument.

Edit #1

If you want to get rid of && !newStr.contains(s) you can use a HashSet<String> instead. I think that is overkill however. .contains(s) will do the trick when the string is small such as this.

Upvotes: 0

Related Questions