有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

映射值的java笛卡尔积

我有如下地图:

{"A" : ["A1", "A2", "A3"], "B" : ["B1", "B2", "B3"]}

我想得到如下数据:

A1, B1
A1, B2
A1, B3
A2, B1
A2, B2
...

我试过如下:

for (String aKey : map.get("A"))
    for (String bKey : map.get("B"))
        // work with aKey + bKey

但这不是我想要的代码,因为地图数据是动态的和不可预知的

因此,我应该获得如下所示的地图数据,但无法按照我的要求制作:

for (String key : map.keySet())
    for (String values : map.get(key))
        // unable to make data I want

共 (2) 个答案

  1. # 1 楼答案

    如果你有一个列表的映射,你可以使用映射和reduce方法获得其值的笛卡尔积。此代码可用于任意数量的列表

    Try it online!

    // a map of lists
    Map<String, List<String>> map = new TreeMap<>();
    map.put("A", Arrays.asList("A1", "A2"));
    map.put("B", Arrays.asList("B1", "B2"));
    map.put("C", Arrays.asList("C1", "C2"));
    
    // cartesian product of the map values
    List<List<String>> cp = map.values().stream()
            // represent each element of a list as a singleton list
            .map(list -> list.stream().map(Arrays::asList)
                    // Stream<List<List<String>>>
                    .collect(Collectors.toList()))
            // summation of pairs of list into a single list
            .reduce((list1, list2) -> list1.stream()
                    // combinations of inner lists
                    .flatMap(inner1 -> list2.stream()
                            // concatenate into a single list
                            .map(inner2 -> Stream.of(inner1, inner2)
                                    .flatMap(List::stream)
                                    .collect(Collectors.toList())))
                    // list of combinations
                    .collect(Collectors.toList()))
            // otherwise an empty list
            .orElse(Collections.emptyList());
    
    // output
    map.forEach((k, v) -> System.out.println(k + ": " + v));
    cp.forEach(System.out::println);
    

    输出:

    A: [A1, A2]
    B: [B1, B2]
    C: [C1, C2]
    [A1, B1, C1]
    [A1, B1, C2]
    [A1, B2, C1]
    [A1, B2, C2]
    [A2, B1, C1]
    [A2, B1, C2]
    [A2, B2, C1]
    [A2, B2, C2]
    

    另见:How to create cartesian product over arbitrary groups of numbers in Java?

  2. # 2 楼答案

    您已经正确地理解了,不能用一组静态嵌套循环创建任意数据的笛卡尔积。您需要的是一组嵌套循环的动态集合。我想你在最后一段代码中也试过了。你似乎也明白,你需要的嵌套循环和数据中的集合一样多。问题仍然是:如何编程动态数量的嵌套循环

    基本上,有两种方法可以实现嵌套循环的动态数量:递归和迭代。两者的效果相同,性能(在时间和内存方面)应该相似。如果实施得好,就是这样

    这里有两个类似的问题,一个明确要求迭代解决方案:

    试着理解两者。你的大脑可能更喜欢其中一个,但至少理解两者是值得的

    递归方法的额外问题,因为递归可能更难理解:Simulating nested loops