<?xml version="1.0"?>
<Event>
<Country>England</Country>
<City>London</City>
<City>Liverpool</City>
<Code>DWW</Code>
<ID>DG300</ID>
<ID>SS500</ID>
<Division>Europe</Division>
</Event>
假设我有一个像上面那样的XML。 我有一个方法,它采用不同数量的参数:
myMethod(String... params){}
参数是我想从XML读取的元素。 举个例子,我们可以从XML
中获取3个元素myMethod(Country, City, ID){}
开始时,我会计算传递给此方法的参数数量:
int count= params.size(); // let say for this example count=3
这里我创建一个以列表作为元素的数组:
List<String>[] tab= new ArrayList[count];
这里我迭代的次数与count参数相等,并在每个数组元素中放入一个列表:
for(int i=0; i<count; i++){
tab[i] = new ArrayList<>();
}
在我的方法中间我有一些循环,它从XML读取元素并将它们放到数组中(将它们添加到列表中)。我使用JAVAX
最后我的数组看起来像这样
tab=[(England),(London,Liverpool),(DG300,SS500)]
现在我遇到了问题。我需要每个列表的笛卡尔,这意味着我需要行:
England London DG300
England London SS500
England Liverpool DG300
England Liverpool SS500
我可以使用像这样的嵌套循环
来做到这一点for(int i=0; i< tab[0].size();i++){
for(int j=0; i< tab[1].size();j++){
for(int k=0; i< tab[2].size();k++){
System.out.println(tab[0].get(i)+ " " + tab[1].get(j)+" "+tab[2].get(k))
}}}}}
但是这不是我在开头提到的好主意,我可以有不同数量的参数,所以我可以有不同数量的嵌套循环。它可以是两个但也可以是十个。
如何使用RECURSION替换此嵌套循环?或者也许我可以使用除递归以外的其他方式做到这一点?
答案 0 :(得分:1)
这是一个解决方案。这是对我的其他帖子的回答的修改:how to use recursion for nested 'for' loops。
public static void iterate(Object[] previousValues, List<Object>[] tabs) {
if (tabs.length == 0) {
System.out.println(Arrays.toString(previousValues));
}
else {
final Object[] values = new Object[previousValues.length + 1];
for (int i = 0; i < previousValues.length; i++) {
values[i] = previousValues[i];
}
final List<Object>[] nextTabs = new List[tabs.length - 1];
for (int i = 0; i < nextTabs.length; i++) {
nextTabs[i] = tabs[i + 1];
}
for (Object o : tabs[0]) {
values[values.length - 1] = o;
iterate(values, nextTabs);
}
}
}
public static void iterate(List<Object>[] tabs) {
iterate(new Object[0], tabs);
}
public static void main(String[] args) {
final List<String> firstTab = new ArrayList<>();
firstTab.add("England");
final List<String> secondTab = new ArrayList<>();
secondTab.add("London");
secondTab.add("Liverpool");
final List<String> thirdTab = new ArrayList<>();
thirdTab.add("DG300");
thirdTab.add("SS500");
iterate(new List[]{firstTab, secondTab, thirdTab});
}
答案 1 :(得分:1)
建议您使用Guava的Lists.cartesianProduct方法:
openCon = new SqlConnection("Data Source=(LocalDB)\\v11.0;" +
"AttachDbFilename=" + AppDomain.CurrentDomain.BaseDirectory + "Encounter.mdf;" +
"Integrated Security=True");
输出:
结果:[[英格兰,伦敦,DG300],[英格兰,伦敦,SS500],[英格兰,廷布,DG300],[英格兰,廷布,SS500],[英格兰,利马,DG300],[英格兰,利马] ,SS500],[不丹,伦敦,DG300],[不丹,伦敦,SS500],[Bhutan,Thimphu,DG300],[不丹,廷布,SS500],[不丹,利马,DG300],[不丹,利马,SS500] ],[秘鲁,伦敦,DG300],[秘鲁,伦敦,SS500],[秘鲁,廷布,DG300],[秘鲁,廷布,SS500],[秘鲁,利马,DG300],[秘鲁,利马,SS500]]
应该注意的是,这个解决方案恰好是一行代码:
答案 2 :(得分:1)
假设您已设置列表以便tab [0]是要打印的第一个字符串的列表,tab [1]以下字符串等,您可以使用递归,如下所示:
void print_rec(List<String>[] tab, int depth, String str) {
int maxdepth = tab.length - 1;
for (int i = 0; i < tab[depth].size(); i++) { // number of strings at this depth
if (depth == maxdepth) {
System.out.println(str + tab[depth].get(i)); // print line
// no more lists to go through, print the line
} else {
print_rec(tab, depth + 1, str + tab[depth].get(i) + " ");
// add next entry at this level to str and recurse
}
}
// done with this depth, go back up one
}
void printAll(List<Strings>[] tab) {
print_rec(tab, 0, "");
}
这涵盖了与嵌套循环完全相同的所有条目。
答案 3 :(得分:0)
在编写递归代码时,我更喜欢先在Haskell中编写函数,然后将其转换回Java。对于我来说,Java对于大局来说太冗长了。
这是我的Haskell实现:
combinations :: [[String]] -> [[String]]
combinations [] = [[]]
combinations (x:xs) = do
ys <- combinations xs
y <- x
return (y:ys)
快速测试以显示it works:
λ> mapM_ print $ combinations [["England"],["London","Liverpool"],["DG300","SS500"]]
["England","London","DG300"]
["England","London","SS500"]
["England","Liverpool","DG300"]
["England","Liverpool","SS500"]
如果你不了解Haskell,那很好。这是combinations
的Java实现:
// combinations :: [[String]] -> [[String]]
public static List<List<String>> combinations(List<List<String>> values) {
// combinations [] = [[]]
if (values.isEmpty()) {
return Arrays.asList(Arrays.asList());
}
// combinations (x:xs) =
List<String> x = values.get(0);
List<List<String>> xs = values.subList(1, values.size());
// do
List<List<String>> outputs = new LinkedList<>();
// ys <- combinations xs
for (List<String> ys : combinations(xs)) {
// y <- x
for (String y : x) {
// (y:ys)
List<String> output = new LinkedList<>();
output.add(y);
output.addAll(ys);
// return
outputs.add(output);
}
}
return outputs;
}
注意:这个Java代码非常低效,因为Haskell具有使递归和链表更有效的优化。优化此代码将是我对读者的挑战。我希望这将具有教育意义(并激励一些人learn Haskell)。