Как мне сгенерировать декартово произведение на Java? - PullRequest
8 голосов
/ 10 ноября 2011

У меня есть число ArrayList, где у каждого ArrayList есть объекты, и каждый из них может иметь различную длину.Мне нужно сгенерировать перестановку, как в следующем примере:

предположим, что у меня есть 2 arraylist

arraylist A имеет объект a, объект b и объект c
arraylist B имеет объект d, объект e

Тогда на выходе должно быть 6 новых массивов с этими комбинациями:

комбинация 1 объекта a и объекта d,
комбинация 2 объекта a и объектаe,
комбинация 3 объекта b и объекта d,
комбинация 4 объекта b и объекта e,
комбинация 5 объекта c и объекта d,
комбинация 6 объекта c и объекта e,

Кто-нибудь может мне помочь?

Ответы [ 5 ]

6 голосов
/ 04 декабря 2016

Гуава 19 +

Lists.cartesianProduct(List...)

* 1005 Е.Г. *:

List<Object> list1 = Arrays.asList("a", "b", "c");
List<Object> list2 = Arrays.asList("d", "e");
System.out.println(Lists.cartesianProduct(list1, list2));

выход

[[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]]
5 голосов
/ 23 октября 2016

С Java8 потоками

    List<String> a = Arrays.asList("a", "b", "c");
    List<String> b = Arrays.asList("d", "e");
    String[][] AB = a.stream().flatMap(ai -> b.stream().map(bi -> new String[] { ai, bi })).toArray(String[][]::new);
    System.out.println(Arrays.deepToString(AB));

выход

    [[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]]

Получить как List

    List<List<String>> ll = a.stream().flatMap(ai -> b.stream().map(bi -> new ArrayList<>(Arrays.asList(ai, bi)))).collect(Collectors.toList());
4 голосов
/ 10 апреля 2012

С помощью Iterable + Iterator:

import java.util.*;

class CartesianIterator <T> implements Iterator <List <T>> {

    private final List <List <T>> lilio;    
    private int current = 0;
    private final long last;

    public CartesianIterator (final List <List <T>> llo) {
        lilio = llo;
        long product = 1L;
        for (List <T> lio: lilio)
            product *= lio.size ();
        last = product;
    } 

    public boolean hasNext () {
        return current != last;
    }

    public List <T> next () {
        ++current;
        return get (current - 1, lilio);
    }

    public void remove () {
        ++current;
    }

    private List<T> get (final int n, final List <List <T>> lili) {
        switch (lili.size ())
        {
            case 0: return new ArrayList <T> (); // no break past return;
            default: {
                List <T> inner = lili.get (0);
                List <T> lo = new ArrayList <T> ();
                lo.add (inner.get (n % inner.size ()));
                lo.addAll (get (n / inner.size (), lili.subList (1, lili.size ())));
                return lo;
            }
        }
    }
}

class CartesianIterable <T> implements Iterable <List <T>> {

    private List <List <T>> lilio;  

    public CartesianIterable (List <List <T>> llo) {
        lilio = llo;
    }

    public Iterator <List <T>> iterator () {
        return new CartesianIterator <T> (lilio);
    }
}

Вы можете использовать их в упрощенном цикле for:

class CartesianIteratorTest {

    public static void main (String[] args) {
        List <Character> la = Arrays.asList (new Character [] {'a', 'b', 'c'});
        List <Character> lb = Arrays.asList (new Character [] {'d', 'e'});      
        List <List <Character>> llc = new ArrayList <List <Character>> ();
        llc.add (la);
        llc.add (lb);

        CartesianIterable <Character> ci = new CartesianIterable <Character> (llc);
        for (List<Character> lo: ci)
            show (lo);
    }

    public static void show (List <Character> lo) {
        System.out.print ("(");
        for (Object o: lo)
            System.out.print (o);
        System.out.println (")");
    }
}
0 голосов
/ 29 октября 2018

Используйте гуаву ... вот пример декартового произведения списка с самим собой:

public static void main(String[] args){
    //How to do a cartesian product of a List of items
    List<Integer> listToSelfMultiply = Arrays.asList(new Integer(1), new Integer(2), new Integer(3), new Integer(4));
    LinkedList<Integer> linkedListCopy = Lists.newLinkedList(listToSelfMultiply);
    for (Integer i:listToSelfMultiply) {
        if(linkedListCopy.size() == 1) {
            break;
        }
        linkedListCopy.remove();
        System.out.println("" + Arrays.deepToString(Lists.cartesianProduct(Arrays.asList(i), linkedListCopy).toArray()) + "");
    }
}
0 голосов
/ 10 ноября 2011

Используйте вложенные для циклов, которые будут иметь цикл для каждого ArrayList, как показано ниже. Я предполагаю, что у меня есть два ArrayList - intList и stringList. Я могу иметь два вложенных для циклов (по одному для каждого списка) для генерации перестановки.

    for(Integer i : intList){
        for (String s : stringList) {
            ...
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...