我有HashMap<GC, List<RR>>
样本数据,如:
key values
gc1 - rr1
- rr2
- rr3
gc2 - rr4
- rr5
gc3 - rr6
我需要从不同的GC创建所有可能的RR组合,如:
Combination1: rr1, rr4, rr6
Combination2: rr1, rr5, rr6
Combination3: rr2, rr4, rr6
Combination4: rr2, rr5, rr6
Combination5: rr3, rr4, rr6
Combination6: rr3, rr5, rr6
到目前为止,我已经尝试过,正如@Sanket Makani建议的那样,将我的HashMap<GC, List<RR>>
转换为List<List<RR>>
,然后遍历所有元素,如:
List<List<RR>> inputList = new ArrayList<List<RR>>();
for (Map.Entry<GC, List<RR>> rrList : Map.entrySet()) {
inputList.add(rrList.getValue());
}
List<List<RR>> combinationsList = new ArrayList<List<RR>>();
for (List<RR> rrList : inputList) {
List<RR> rrList1 = new ArrayList<RR>();
for (RR rr : rrList) {
rrList1.add(rr);
}
combinationsList.add(rrList1);
}
这对我不起作用,因为它将一个GC中的所有RR分组为:
Combination1: rr1, rr2, rr3
Combination2: rr4, rr5
Combination3: rr6
所以我的问题是,我如何调整我的代码以获得预期的结果?
PS:遗憾的是我正在使用Java6,因此不允许使用lambdas / stream。
PS2:我见过类似的问题,但找不到我想要的确切示例。
编辑:
这是我在@nandsito的回答中的最终实现:
//this method groups RRs by GC key with a given list
HashMap<GC, List<RR>> GCRRHashMap = groupRRsByGC(list);
List<Map.Entry<GC, List<RR>>> mapEntryList = new ArrayList<Map.Entry<GC, List<RR>>>(GCRRHashMap.entrySet());
List<List<RR>> combinationsList = new ArrayList<List<RR>>();
List<RR> combinations = new ArrayList<RR>();
generateCombinations(mapEntryList, combinations, combinationsList);
private void generateCombinations(
List<Map.Entry<GC, List<RR>>> mapEntryList,
List<RR> combinations, List<List<RR>> combinationsList) {
if (mapEntryList.isEmpty()) {
combinationsList.add(new ArrayList<RoomStay>(combinations));
return;
}
Map.Entry<GC, List<RR>> entry = mapEntryList.remove(0);
List<RR> entryValue = new ArrayList<RR>(entry.getValue());
while (!entryValue.isEmpty()) {
RR rr = entryValue.remove(0);
combinations.add(rr);
generateCombinations(mapEntryList, combinations, combinationsList);
combinations.remove(combinations.size() - 1);
}
mapEntryList.add(0, entry);
}
答案 0 :(得分:2)
这是一个递归解决方案:
public static void main(String[] args) {
// your data map
Map<GC, List<RR>> map;
// the map entry set as list, which will help
// combining the elements
//
// note this is a modifiable list
List<Map.Entry<GC, List<RR>>> mapEntryList =
new ArrayList<Map.Entry<GC, List<RR>>>(map.entrySet());
// the combinations list, which will store
// the desired results
List<RR> combinations = new ArrayList<RR>();
doRecursion(mapEntryList, combinations);
}
private static void doRecursion(
List<Map.Entry<GC, List<RR>>> mapEntryList,
List<RR> combinations) {
// end of recursion
if (mapEntryList.isEmpty()) {
// do what you wish
//
// here i print each element of the combination
for (RR rr : combinations) {
System.out.println(rr);
}
System.out.println();
return;
}
// remove one GC from the entry list,
// then for each RR from the taken GC
// put RR in the combinations list,
// call recursion
// the remove RR from the combinations list
// end for each
// then put GC back into its list
Map.Entry<GC, List<RR>> entry = mapEntryList.remove(0);
List<RR> entryValue = new ArrayList<RR>(entry.getValue());
while (!entryValue.isEmpty()) {
RR rr = entryValue.remove(0);
combinations.add(rr);
doRecursion(mapEntryList, combinations);
combinations.remove(combinations.size() - 1);
}
mapEntryList.add(0, entry);
}
答案 1 :(得分:1)
您真正需要做的就是通过递增索引列表:
0,0,0
0,1,0
1,0,0
1,1,0
2,0,0
... etc.
如何将每个行转换为数据结构中的值应该是显而易见的。例如0,0,0
映射到rr1, rr4, rr6
。这将涉及将地图转换为列表,以使索引保持一致。
它非常类似于正常的base-b计数,你增加最右边的列,如果它溢出,设置为零并递增下一列。唯一的区别是每列溢出的数字不同。
所以:
boolean increment(int[] indexes) {
int column = 0;
while(true) {
indexes[column]++;
if(indexes[column] < numberOfRRsInColumn(column)) {
return true; // finished
}
indexes[column]=0;
column++;
if(column = indexes.length) {
return false; // can't increment, no more.
}
}
}
此实现使用indexes[0]
作为“最右侧”列。我已经掩饰了numberOfRRsInColumn()
,但是如何做到这一点应该非常明显。
然后:
int[] indexes = new int[mapsize];
do {
output(translate(map, indexes));
} while (increment(indexes));