简体   繁体   English

Java动态嵌套循环

[英]Java dynamic nested loops

I have a map which contains variable length string list.我有一个包含可变长度字符串列表的地图。 eg例如

Map<String, List<String> map = new HashMap<>();
map.put("key", "key1, key2);
map.put("name", "name1, name2, name3");
map.put("code", "code1, code2");

This will give 12 different permutations.这将给出 12 种不同的排列。 The below code does that job下面的代码完成这项工作

List<String> values = new ArrayList<>();
for (int i = 0; i < map.get("key").size(); i++) {
     values.add(map.get("key").get(i));
     for (int j = 0; j < map.get("name").size(); j++) {
         values.add(map.get("name").get(j));
         for (int k = 0; k < map.get("code").size(); k++) {
             values.add(map.get("code").get(k));
         }
     }
}

Expected output:预期输出:

"key1", "name1", "code1",
"key1", "name1", "code2",
"key1", "name2", "code1",
"key1", "name2", "code2",
"key1", "name3", "code1",
"key1", "name3", "code2",
"key2", "name1", "code1",
"key2", "name1", "code2",
"key2", "name2", "code1",
"key2", "name2", "code2",
"key2", "name3", "code1",
"key2", "name3", "code2"

But the problem is this is hard coded with 3 for loops, but what I expect is to support for any number of variables.但问题是这是用 3 个 for 循环硬编码的,但我期望的是支持任意数量的变量。 Prompt help is much appreciated.非常感谢及时的帮助。

Following snippet solves this problem.以下代码段解决了这个问题。

    protected static void traverseParam(Map<String, List<String>> paramLists, int level, Map<String, String> paramMap) {
                if (level == paramLists.size()) {
                   //contains of all combinations
                    System.out.println(StringUtils.join(paramMap.values(), ", "));
                } else {
                    String paramKey = (String) paramLists.keySet().toArray()[level];
                    List<String> paramValues = (List<String>) paramLists.values().toArray()[level];
                    for (String paramValue : paramValues) {
                        paramMap.put(paramKey, paramValue);
                        //Recursively calls until all params are processed
                        traverseParam(paramLists, level + 1, paramMap);
                    }
                }
            }

Now call this method like below.现在像下面这样调用这个方法。

Map<String, List<String> map = new HashMap<>();
map.put("key", "key1, key2);
map.put("name", "name1, name2, name3");
map.put("code", "code1, code2");
//Start with 1st parameter, and pass 
//an empty LinkedHashMap and all entries will be added to this map.
traverseParam(map, 0, new LinkedHashMap<String, String>());

I provided below a sample solution, using recursion.我在下面提供了一个示例解决方案,使用递归。

In the example we have 3 lists, with rep.在这个例子中,我们有 3 个列表,代表。 3,4,4 elements; 3、4、4个元素; the program prints all 3*4*4=48 combinations of elements.该程序打印所有 3*4*4=48 个元素组合。

Starting with an empty combination (an empty list), at each step(i) we take N=list(i).size() copies of the current tuple, add value(j)=list(i)[j] to the j-th new tuple (for j=1..N), and recurse.从一个空组合(一个空列表)开始,在每一步(i)我们取当前元组的 N=list(i).size() 个副本,将 value(j)=list(i)[j] 添加到第 j 个新元组(对于 j=1..N),然后递归。 When i=list.size, then the tuple is complete and we can use it (eg. print it out).当 i=list.size 时,元组是完整的,我们可以使用它(例如打印出来)。 (lists can be copied using the constructor). (可以使用构造函数复制列表)。

package sample;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.function.Consumer;

public class SampleCombinations {

  public static void main(String[] args) {

    Map<String, List<String>> map = new TreeMap<>();
    map.put("x", Arrays.asList("a", "b", "c"));
    map.put("y", Arrays.asList("0", "1", "2", "3"));
    map.put("z", Arrays.asList("!", "-", "=", "%"));

    ArrayList<Entry<String, List<String>>> entries = new ArrayList<>(map.entrySet());

    System.out.println(entries);
    printCombinations(entries);
  }

  private static void printCombinations(List<Entry<String, List<String>>> entries) {
    Consumer<List<String>> cons = list -> System.out.println(list);
    generateComb(entries, cons, 0, new LinkedList<>());
  }

  private static void generateComb(List<Entry<String, List<String>>> entries,
      Consumer<List<String>> consumer, int index, List<String> currentTuple) {

    /*
     * terminal condition: if i==entries.size the tuple is complete
     * consume it and return
     */
    if(index==entries.size()) {
      consumer.accept(currentTuple);
    }
    else {
      /*
       * get all elements from the i-th list, generate N new tuples and recurse
       */
      List<String> elems = entries.get(index).getValue();
      for (String elem:elems) {
        // copy the current tuple
        LinkedList<String> newTuple = new LinkedList<>(currentTuple);
        newTuple.add(elem);
        generateComb(entries, consumer, index+1, newTuple);
      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM