[英]How to make combination from values of of LinkedHashMap<String, ArrayList<ArrayList>>
Suppose we have below LinkedHashMap<String, ArrayList<ArrayList>>假设我们有下面的 LinkedHashMap<String, ArrayList<ArrayList>>
{FRA=[[1, 2], [3, 4]], MEL=[[5, 6]]}
The output should be output 应该是
[1,2,5,6], [3,4,5,6]
Similarly if input is:同样,如果输入是:
{SFO=[[1]], SEA=[[2], [3], [4]], PHX=[[5], [6]]}
Then expected output is然后预计 output 是
[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6]
I have tried below code, but did not get the expected result.我试过下面的代码,但没有得到预期的结果。
public static ArrayList<List<String>> getCombinations(ArrayList<ArrayList<String>> valueSetList) {
int comboCount = 1;
for (List<String> valueSet : valueSetList)
comboCount = Math.multiplyExact(comboCount, valueSet.size()); // Fail if overflow
ArrayList<List<String>> combinations = new ArrayList<>(comboCount);
for (int comboNumber = 0; comboNumber < comboCount; comboNumber++) {
List<String> combination = new ArrayList<>(valueSetList.size());
int remain = comboNumber;
for (List<String> valueSet : valueSetList) {
combination.add(valueSet.get(remain % valueSet.size()));
remain /= valueSet.size();
}
combinations.add(combination);
}
return combinations;
}
Any help is highly appreciated.非常感谢任何帮助。
The following recursive solution is based on Philipp Meister's answer to similar question about building of the Cartesian product :以下递归解决方案基于Philipp Meister对有关构建笛卡尔积的类似问题的回答:
static List<List<Integer>> merge(List<List<List<Integer>>> lists) {
List<List<Integer>> resultLists = new ArrayList<>();
if (lists.size() == 0) {
resultLists.add(new ArrayList<>());
} else {
List<List<Integer>> firstList = lists.get(0);
List<List<Integer>> remainingLists = merge(lists.subList(1, lists.size()));
for (List<Integer> first : firstList) {
for (List<Integer> remaining : remainingLists) {
List<Integer> resultList = new ArrayList<>();
resultList.addAll(first);
resultList.addAll(remaining);
resultLists.add(resultList);
}
}
}
return resultLists;
}
Main difference is in the return type and adding all elements of the first
list to the nested list according to the requirements.主要区别在于返回类型和根据要求将
first
列表的所有元素添加到嵌套列表中。
Test setup测试设置
private static void testCombinations(Map<String, List<List<Integer>>> map) {
System.out.println("input map: " + map);
List<List<Integer>> list = merge(new ArrayList<>(map.values()));
list.forEach(System.out::println);
}
// --------
Map<String, List<List<Integer>>> map1 = new LinkedHashMap<>();
map1.put("SFO", Arrays.asList(Arrays.asList(1)));
map1.put("SEA", Arrays.asList(Arrays.asList(2), Arrays.asList(3), Arrays.asList(4)));
map1.put("PHX", Arrays.asList(Arrays.asList(5), Arrays.asList(6)));
testCombinations(map1);
Map<String, List<List<Integer>>> map2 = new LinkedHashMap<>();
map2.put("FRA", Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4)));
map2.put("MEL", Arrays.asList(Arrays.asList(5, 6)));
testCombinations(map2);
Output: Output:
input map: {SFO=[[1]], SEA=[[2], [3], [4]], PHX=[[5], [6]]}
[1, 2, 5]
[1, 2, 6]
[1, 3, 5]
[1, 3, 6]
[1, 4, 5]
[1, 4, 6]
input map: {FRA=[[1, 2], [3, 4]], MEL=[[5, 6]]}
[1, 2, 5, 6]
[3, 4, 5, 6]
The solution may be implemented using streams and recursive flatMap
chain (on the basis of Marco13's answer ):该解决方案可以使用流和递归
flatMap
链来实现(基于Marco13 的回答):
static <T extends List> Stream<List<T>> ofCombinations(List<? extends Collection<T>> mapValues, List<T> current) {
return mapValues.isEmpty() ? Stream.of(current) :
mapValues.get(0).stream().flatMap(list -> {
List<T> combination = new ArrayList<T>(current);
combination.addAll(list);
return ofCombinations(mapValues.subList(1, mapValues.size()), combination);
});
}
private static void testStreamCombinations(Map<String, List<List<Integer>>> map) {
System.out.println("input map: " + map);
ofCombinations(new ArrayList<>(map.values()), Collections.emptyList())
.forEach(System.out::println);
}
// invoking test method
testStreamCombinations(map1);
testStreamCombinations(map2);
Test output: same as above.测试output:同上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.