生成列表映射到列表列表的所有组合

时间:2012-05-17 17:58:05

标签: java collections recursion

我有一个Map<Integer, List<Float>>代表一个有一些分数的职位,我想生成每个职位的所有可能的分数组合(基本上是原始地图中每个列表的交叉积)到{{ 1}}。所以我要说我有以下地图:

List<List<Float>>

我想获得以下浮动列表列表:

{ 1 => [0.1f, 0.2f], 2 => [0.3f, 0.4f] }

我很确定我必须使用递归,只是不确定如何继续它...

欢迎任何帮助,谢谢。

4 个答案:

答案 0 :(得分:1)

每当你有一个递归算法来编码时,你需要一个归纳定义来帮助设计它。

基本情况:{}↦[]
归纳步骤:M↦L⇒(M∪{n↦S})↦L×S

对于S中的每个元素,将其添加到L中每个列表的末尾,并将结果列表添加到输出中。

List< List< Float > > llfNext = new LinkedList< List< Float > >();
for ( float f : entEach.getValue() )
    for ( List< Float > lfEach : llfInductive )            
        llfNext.add( copyAndAddToEnd( lfEach, f ) );
return llfNext;

从这里开始应该很简单,然后你可以使它非递归并减少一些复制。

答案 1 :(得分:1)

使用Java 9,您可以将列表映射的所有组合生成为映射列表,如下所示:

Map<Integer, List<Float>> mapOfLists = new LinkedHashMap<>();
mapOfLists.put(1, List.of(0.1f, 0.2f));
mapOfLists.put(2, List.of(0.3f, 0.4f));
mapOfLists.put(3, List.of(0.5f, 0.6f));
List<Map<Integer, Float>> listOfMaps = mapOfLists.entrySet().stream()
        // Stream<List<Map<Integer,Float>>>
        .map(entry -> entry.getValue().stream()
                // represent list elements as Map<Integer,Float>
                .map(element -> Map.of(entry.getKey(), element))
                // collect a list of maps
                .collect(Collectors.toList()))
        // intermediate output
        //[{1=0.1}, {1=0.2}]
        //[{2=0.3}, {2=0.4}]
        //[{3=0.5}, {3=0.6}]
        .peek(System.out::println)
        // reduce a stream of lists to a single list
        // by sequentially multiplying the list pairs
        .reduce((list1, list2) -> list1.stream()
                // combinations of elements,
                // i.e. maps, from two lists
                .flatMap(map1 -> list2.stream()
                        .map(map2 -> {
                            // join entries of two maps
                            Map<Integer, Float> map =
                                    new LinkedHashMap<>();
                            map.putAll(map1);
                            map.putAll(map2);
                            return map;
                        }))
                // collect into a single list
                .collect(Collectors.toList()))
        .orElse(null);
// output a list of map values
listOfMaps.stream().map(Map::values).forEach(System.out::println);
//[0.1, 0.3, 0.5]
//[0.1, 0.3, 0.6]
//[0.1, 0.4, 0.5]
//[0.1, 0.4, 0.6]
//[0.2, 0.3, 0.5]
//[0.2, 0.3, 0.6]
//[0.2, 0.4, 0.5]
//[0.2, 0.4, 0.6]

另见:Convert a map of lists into a list of maps

答案 2 :(得分:0)

如果您解决了如何创建不同的排列,那么您已经完成了很多工作,并且可以使用两个for循环来完成

答案 3 :(得分:0)

  List<List<Float>> finalList = new ArrayList<List<Float>>();
  int pointsCounter = 0;
  for(Integer key:map.keys()){
    List<Float> scoresList = map.get(key);
    boolean firstValue = true;
    for(Float score: scoresList){
      if(firstValue) {
        finalList.add(new ArrayList<Float>());
        firstValue = false;
      }
      finalList.get(pointsCounter).add(score);
    }
    pointsCounter++;
  }