大量的笛卡尔积

时间:2020-03-24 19:58:30

标签: java algorithm

我有[[price -> 0.5, comission -> 50.0, quantity -> 20.0], [price -> 1.0, comission -> 50.0, quantity -> 20.0], [price -> 10.0, comission -> 50.0, quantity -> 20.0]] ,需要从中生成笛卡尔积。我试图使用Unable to resolve "abort-controller/dist/abort-controller" from "node_modules/react-native/Libraries/Core/setUpXHR.js" Failed building JavaScript bundle. ,但是问题是笛卡尔积的大小大于List<List<T>> input,并且方法引发异常。我在网上找到的所有算法都有类似的问题(如果您想保留完整的列表功能,则它们受Lists.cartesianProduct(input)的最大大小限制,Integer.MAX_VALUE的限制)。我想到的唯一解决方案是创建用List而不是Integer.MAX_VALUE索引的我自己的列表实现,但是我将无法使用long接口,这将非常麻烦,因此真的是不得已。还有其他解决方法吗?只要我具有所有可能的组合,输出就不必是List。

1 个答案:

答案 0 :(得分:1)

构建一个在笛卡尔乘积上迭代并调用用户提供的函数而不是构建它们的列表的解决方案非常容易。这样,完整的产品就永远不会存储在内存中。如果您希望将结果存储在文件中,也可以这样做,只需提供一个写入文件的函数即可。

<T> void cartesianProduct(List<List<T>> items, Consumer<List<T>> consumer) {
    recurse(items, consumer, new ArrayList<>());
}

<T> void recurse(List<List<T>> items, Consumer<List<T>> consumer, List<T> prefix) {
    if (items.isEmpty()) {
        consumer.accept(prefix);
    } else {
        List<T> first = items.get(0);
        List<List<T>> rest = items.subList(1, items.size());
        for (T item : first) {
            prefix.add(item);
            recurse(rest, consumer, prefix);
            prefix.remove(prefix.size() - 1);
        }
    }
}

例如,这会将笛卡尔乘积打印到System.out:

cartesianProduct(List.of(
    List.of("1", "2"), List.of("A", "B"), List.of("!", "@")
), System.out::println);