Reputation: 4372
My input string is
element1-element2-element3-element4a|element4b-element5-
Expected output is
element1-element2-element3-element4a-element5-
element1-element2-element3-element4b-element5-
So the dash (-) is the delimiter and the pipe (|) indicates two alternative elements for a position.
I am able to generate combinations for input containing a single pipe:
ArrayList<String> finalInput = new ArrayList<String>();
String Input = getInputPath();
StringBuilder TempInput = new StringBuilder();
if(Input.contains("|")) {
String[] splits = Input.split("\\|", 2);
TempInput.append(splits[0]+"-"+splits[1].split("-", 2)[1]);
finalInput.add(TempInput.toString());
TempInput = new StringBuilder();
String[] splits1 = new StringBuilder(Input).reverse().toString().split("\\|", 2);
finalInput.add(TempInput.append(splits1[0]+"-"+splits1[1].split("-", 2)[1]).reverse().toString());
}
But this logic fails if there are multiple pipe symbols.
Is there any efficient way to use split String with combinations?
Input:
element1-element2-element3-element4a|element4b-element5-element6a|element6b
Output:
element1-element2-element3-element4a-element5-element6a
element1-element2-element3-element4b-element5-element6a
element1-element2-element3-element4a-element5-element6b
element1-element2-element3-element4b-element5-element6b
Upvotes: 2
Views: 1735
Reputation: 364
This helps to acheive the same..
public class MultiStringSplitter {
public static void main(String arg[]) {
String input = "a-b|c-d|e-f|g-h";
String[] primeTokens = input.split("-");
String[] level2Tokens = null;
String element = "";
String level2element = "";
ArrayList stringList = new ArrayList();
ArrayList level1List = new ArrayList();
ArrayList level2List = new ArrayList();
for (int i = 0; i < primeTokens.length; i++) {
// System.out.print(primeTokens[i]);
if (primeTokens[i].contains("|")) {
level2Tokens = primeTokens[i].split("\\|");
for (int j = 0; j < level2Tokens.length; j++) {
for (int k = 0; k < stringList.size(); k++) {
element = (String) stringList.get(k);
level2element = element + level2Tokens[j];
level2List.add(level2element);
}
}
stringList = new ArrayList();
for (int w = 0; w < level2List.size(); w++) {
stringList.add(level2List.get(w));
}
level2List = new ArrayList();
}
else {
if (stringList.size() > 0) {
for (int z = 0; z < stringList.size(); z++) {
element = (String) stringList.get(z);
element = element + primeTokens[i];
level1List.add(element);
}
stringList = new ArrayList();
for (int w = 0; w < level1List.size(); w++) {
stringList.add(level1List.get(w));
}
level1List = new ArrayList();
}
else {
element = element + primeTokens[i];
if (stringList.size() == 0) {
stringList.add(element);
}
}
}
}
for (int q = 0; q < stringList.size(); q++) {
System.out.println(stringList.get(q));
}
}
}
Input : a-b|c-d|e-f|g-h
Output:
abdfh
acdfh
abefh
acefh
abdgh
acdgh
abegh
acegh
Upvotes: 0
Reputation: 16209
Here's my iterative solution:
import java.util.*;
public class PathParser {
private static final String DELIMINATOR_CONCAT = "-";
private static final String DELIMINATOR_OPTION = "|";
private List<String> paths;
private List<String> stack;
private List<String> parse(final String pathSpec) {
stack = new ArrayList<String>();
paths = new ArrayList<String>();
paths.add("");
final StringTokenizer tok = createStringTokenizer(pathSpec);
while (tok.hasMoreTokens()) {
final String token = tok.nextToken();
parseToken(token);
}
if (!stack.isEmpty()) {
updatePaths();
}
return paths;
}
private void parseToken(final String token) {
if (DELIMINATOR_CONCAT.equals(token)) {
updatePaths();
} else if (DELIMINATOR_OPTION.equals(token)) {
// nothing to do
} else {
stack.add(token);
}
}
private void updatePaths() {
final List<String> originalPaths = new ArrayList<String>(paths);
paths.clear();
while (stack.size() > 0) {
paths.addAll(createNewPaths(originalPaths));
}
}
private List<String> createNewPaths(final List<String> originalPaths) {
final List<String> newPaths = new ArrayList<String>(originalPaths);
addPart(newPaths, stack.remove(0));
addPart(newPaths, DELIMINATOR_CONCAT);
return newPaths;
}
private void addPart(final List<String> paths, final String part) {
for (int i = 0; i < paths.size(); i++) {
paths.set(i, paths.get(i) + part);
}
}
private StringTokenizer createStringTokenizer(final String pathSpec) {
final boolean returnDelimiters = true;
final String delimiters = DELIMINATOR_CONCAT + DELIMINATOR_OPTION;
return new StringTokenizer(pathSpec, delimiters, returnDelimiters);
}
public static void main(final String[] args) {
final PathParser pathParser = new PathParser();
final String input = "element1-element2-element3-element4a|element4b|element4c-element5-element6a|element6b|element6c";
System.out.println("Input");
System.out.println(input);
System.out.println();
final List<String> paths = pathParser.parse(input);
System.out.println("Output");
for (final String path : paths) {
System.out.println(path);
}
}
}
Output:
Input
element1-element2-element3-element4a|element4b-element5-element6a|element6b
Output
element1-element2-element3-element4a-element5-element6a-
element1-element2-element3-element4b-element5-element6a-
element1-element2-element3-element4a-element5-element6b-
element1-element2-element3-element4b-element5-element6b-
Upvotes: 0
Reputation: 109597
Recursion helps.
public static void main(String[] args) {
produce("element1-element2-element3-element4a|element4b"
+ "-element5-element6a|element6b");
}
private static void produce(String input) {
String[] sequence = input.split("-");
String[][] elements = new String[sequence.length][];
for (int i = 0; i < sequence.length; ++i) {
elements[i] = sequence[i].split("\\|");
}
List<String> results = new ArrayList<>();
walk(results, elements, 0, new StringBuilder());
}
private static void walk(List<String> results, String[][] elements,
int todoIndex, StringBuilder done) {
if (todoIndex >= elements.length) {
results.add(done.toString());
System.out.println(done);
return;
}
int doneLength = done.length();
for (String alternative : elements[todoIndex]) {
if (done.length() != 0) {
done.append('-');
}
done.append(alternative);
walk(results, elements, todoIndex + 1, done);
done.setLength(doneLength); // Undo
}
}
The String.split
method is used twice to get a navigatable String[][]
. And to build a final String a StringBuilder
is used.
Upvotes: 5
Reputation: 9065
I have write a demo for you as what I comment after your post, the code may be ugly, but it works
public class TestSplit {
//define a stringList hold our result.
private static List<String> stringList = new ArrayList<String>();
//this method fork the list array when we meet a "|"
public static void forkStringList(){
List<String> tmpList = new ArrayList<String>();
for(String s: stringList){
tmpList.add(s);
}
stringList.addAll(tmpList);
}
//when we meet "|" split two elems, should add it to
//the string list half-half
public static void addTowElems(String s1, String s2){
for(int i=0;i<stringList.size()/2;i++){
stringList.set(i,stringList.get(i)+s1);
}
for(int i = stringList.size()/2;i<stringList.size();i++){
stringList.set(i,stringList.get(i)+s2);
}
}
// if not meet with a "|" just add elem to everyone of the stringlist
public static void addOneElem(String s){
for(int i=0;i<stringList.size();i++){
stringList.set(i,stringList.get(i)+s);
}
}
public static void main(String[] argvs){
//to make *fork* run, we must make sure there is a "init" string
//which is a empty string.
stringList.add("");
// this is your origin string.
String input = "a-b-c-d|e-f";
for (String s: input.split("\\-")){
if(s.contains("|")){
//when meet with "|", first fork the stringlist
forkStringList();
// then add them separately
addTowElems(s.split("\\|")[0],s.split("\\|")[1]);
}else {
// else just happily add the elem to every one
// of the stringlist
addOneElem(s);
}
}
//checkout the result, should be expected.
System.out.println(stringList);
}
}
Upvotes: 1
Reputation: 3748
You can use StringTokenizer in Java. Basically it makes tokens of the string.
public StringTokenizer(String str, String delim)
Here's an example:
String msg = "http://100.15.111.60:80/";
char tokenSeparator= ':';
StringTokenizer st = new StringTokenizer(msg, tokenSeparator + "");
while(st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
Upvotes: 1