1

I have a map which contains variable length string list. e.g

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. 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. Prompt help is much appreciated.

1
  • 1
    This code isn't generating permutations. What do you want/expect to be in the values map after it's done?CommentedNov 24, 2019 at 19:24

2 Answers 2

1

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>()); 
    0

    I provided below a sample solution, using recursion.

    In the example we have 3 lists, with rep. 3,4,4 elements; the program prints all 3*4*4=48 combinations of elements.

    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. When i=list.size, then the tuple is complete and we can use it (eg. print it out). (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); } } } } 

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.