Producto cartesiano de un número arbitrario de conjuntos.

Resuelto mgamer asked hace 15 años • 11 respuestas

¿Conoce algunas bibliotecas Java interesantes que le permitan crear un producto cartesiano de dos (o más) conjuntos?

Por ejemplo: tengo tres juegos. Uno con objetos de clase Persona, segundo con objetos de clase Regalo y tercero con objetos de clase GiftExtension.

Quiero generar un conjunto que contenga todos los triples posibles Persona-Regalo-Extensión de Regalo.

El número de conjuntos puede variar, por lo que no puedo hacer esto en un bucle foreach anidado. En algunas condiciones, mi aplicación necesita crear un producto del par Persona-Regalo, a veces es triple Persona-Regalo-Extensión de Regalo, a veces incluso puede haber conjuntos Persona-Regalo-Extensión de Regalo-RegaloSecondExtension-GiftThirdExtension, etc.

mgamer avatar Apr 03 '09 21:04 mgamer
Aceptado

Editar: Se eliminaron las soluciones anteriores para dos conjuntos. Consulte el historial de edición para obtener más detalles.

Aquí hay una manera de hacerlo de forma recursiva para un número arbitrario de conjuntos:

public static Set<Set<Object>> cartesianProduct(Set<?>... sets) {
    if (sets.length < 2)
        throw new IllegalArgumentException(
                "Can't have a product of fewer than two sets (got " +
                sets.length + ")");

    return _cartesianProduct(0, sets);
}

private static Set<Set<Object>> _cartesianProduct(int index, Set<?>... sets) {
    Set<Set<Object>> ret = new HashSet<Set<Object>>();
    if (index == sets.length) {
        ret.add(new HashSet<Object>());
    } else {
        for (Object obj : sets[index]) {
            for (Set<Object> set : _cartesianProduct(index+1, sets)) {
                set.add(obj);
                ret.add(set);
            }
        }
    }
    return ret;
}

Tenga en cuenta que es imposible conservar información de tipo genérico con los conjuntos devueltos. Si supiera de antemano de cuántos conjuntos desea tomar el producto, podría definir una tupla genérica para contener esa cantidad de elementos (por ejemplo Triple<A, B, C>), pero no hay forma de tener un número arbitrario de parámetros genéricos en Java.

Michael Myers avatar Apr 03 '2009 14:04 Michael Myers

Esta es una pregunta bastante antigua, pero ¿por qué no utilizar el producto cartesiano de Guava ?

Martin Andersson avatar Nov 15 '2013 12:11 Martin Andersson

El siguiente método crea el producto cartesiano de una lista de cadenas:

protected <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
    List<List<T>> resultLists = new ArrayList<List<T>>();
    if (lists.size() == 0) {
        resultLists.add(new ArrayList<T>());
        return resultLists;
    } else {
        List<T> firstList = lists.get(0);
        List<List<T>> remainingLists = cartesianProduct(lists.subList(1, lists.size()));
        for (T condition : firstList) {
            for (List<T> remainingList : remainingLists) {
                ArrayList<T> resultList = new ArrayList<T>();
                resultList.add(condition);
                resultList.addAll(remainingList);
                resultLists.add(resultList);
            }
        }
    }
    return resultLists;
}

Ejemplo:

System.out.println(cartesianProduct(Arrays.asList(Arrays.asList("Apple", "Banana"), Arrays.asList("Red", "Green", "Blue"))));

produciría esto:

[[Apple, Red], [Apple, Green], [Apple, Blue], [Banana, Red], [Banana, Green], [Banana, Blue]]
Philipp Meister avatar Feb 29 '2012 09:02 Philipp Meister