我有一个以下结构的字符串: A1(N1,N2,N3)P4(O3,O5)Y1
如何获得所有组合?规则是括号内的选项不应该在一起。对于此示例,输出应为:
A1N1P4O3Y1,
A1N2P4O3Y1,
A1N3P4O3Y1,
A1N1P4O5Y1,
A1N2P4O5Y1,
A1N3P4O5Y1.
可以有括号,但也可以没有它。另一个例子:
N3P5(L1,L2)Q1,输出应为:
N3P5L1Q1,
N3P5L2Q1.
有优雅解决方案的人吗?
答案 0 :(得分:0)
主要思想是将字符串输入转换为包含部分的StringTemplate,可以是单个字符串或一组字符串。
对于每个部件,都会创建一个迭代器。虽然可以使用一些迭代器,但更新一个包含当前零件值的字符串数组,并重置在更改的零件之前的所有零件迭代器。如果需要,请随意清除重复的代码并添加嵌套组支持和语法验证。
private static StringTemplate parse(String string) {
List<StringPart> parts = new ArrayList<StringPart>();
boolean insideGroup = false;
StringBuilder currentToken = new StringBuilder();
List<LiteralPart> groupParts = new ArrayList<LiteralPart>();
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
if (ch == '(') {
if (currentToken.length() != 0) {
parts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
insideGroup = true;
} else if (ch == ')') {
if (insideGroup) {
if (currentToken.length() != 0) {
groupParts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
parts.add(new CompositePart(groupParts));
groupParts.clear();
insideGroup = false;
} else {
currentToken.append(ch);
}
} else if (ch == ',') {
if (insideGroup) {
if (currentToken.length() != 0) {
groupParts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
} else {
currentToken.append(ch);
}
} else {
currentToken.append(ch);
}
}
if (currentToken.length() != 0) {
parts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
return new StringTemplate(parts);
}
private static final class StringTemplate {
private final List<StringPart> parts;
public StringTemplate(List<StringPart> parts) {
this.parts = parts;
}
public List<String> getCombinations() {
List<Iterator<String>> iterators = new ArrayList<Iterator<String>>(parts.size());
for (StringPart part : parts) {
iterators.add(part.getStrings().iterator());
}
String[] toJoin = new String[iterators.size()];
List<String> combinations = new ArrayList<String>();
int iteratorThatAdvanced;
int maxIteratorThatAdvanced = Integer.MIN_VALUE;
boolean first = true;
for (;;) {
iteratorThatAdvanced = -1;
for (int i = 0; i < iterators.size(); i++) {
Iterator<String> iterator = iterators.get(i);
if (first || iterator.hasNext()) {
String value = iterator.next();
toJoin[i] = value;
iteratorThatAdvanced = i;
if (!first && i >= maxIteratorThatAdvanced) {
maxIteratorThatAdvanced = i;
break;
}
}
}
if (iteratorThatAdvanced < 0) {
break;
}
if (!first) {
for (int i = 0; i < iteratorThatAdvanced; i++) {
Iterator<String> iterator = parts.get(i).getStrings().iterator();
iterators.set(i, iterator);
toJoin[i] = iterator.next();
}
}
combinations.add(join(toJoin));
first = false;
}
return combinations;
}
}
private static String join(String[] strings) {
StringBuilder builder = new StringBuilder();
for (String string : strings) {
builder.append(string);
}
return builder.toString();
}
private static abstract class StringPart {
abstract List<String> getStrings();
}
private static final class LiteralPart extends StringPart {
private final String literal;
public LiteralPart(String literal) {
this.literal = literal;
}
@Override
List<String> getStrings() {
return Collections.singletonList(literal);
}
}
private static final class CompositePart extends StringPart {
private final List<LiteralPart> parts;
public CompositePart(List<LiteralPart> parts) {
this.parts = new ArrayList<LiteralPart>(parts);
}
@Override
List<String> getStrings() {
List<String> strings = new ArrayList<String>(parts.size());
for (LiteralPart part : parts) {
strings.add(part.literal);
}
return strings;
}
}
示例:
public static void main(String[] args) {
StringTemplate template = parse("A1(N1,N2,N3)P4(O3,O5)Y1");
for (String combination : template.getCombinations()) {
System.out.println(combination);
}
template = parse("N3P5(L1,L2)Q1");
for (String combination : template.getCombinations()) {
System.out.println(combination);
}
}