Получить список комбинаций элементов списков
Предположим, у меня есть 3 списка: ['q','w'], ['a','s'], ['z','x']. Как получить список возможных комбинаций из этих списков? Поэтому я получаю список [['q','a','z'],['q','s','z']] и тому подобное. Я сделал метод для двоих, но не могу изобразить один для N списков:
static <E> ArrayList combine(ArrayList<E> one,ArrayList<E> two)
{
ArrayList<ArrayList<E>> combs=new ArrayList<ArrayList<E>>();
for(E e:one)
{
for(E e2:two)
{
ArrayList ps=new ArrayList();
ps.add(e);
ps.add(e2);
combs.add(ps);
}
}
return combs;
}
Я узнал, что это сделано с помощью Sets.cartesianProduct компании Guava.
4 ответа
Вам нужно N вложенных циклов, что делает его сложным.
Вы можете добиться этого с помощью рекурсии, хотя.
static <E> ArrayList combine(ArrayList<E> soFar, ArrayList<E>... lists)
{
// Rather than constantly making and remaking this list could just use one
// and pass it around and add stuff to it. This works though.
ArrayList<ArrayList<E>> combs=new ArrayList<ArrayList<E>>();
// Loop through the first list looking for elements
for(E e:lists[0])
{
// Create a new List to build this combination
ArrayList<E> temp = new ArrayList<>(soFar);
// Add this element to the combination
temp.add(e);
// If there are more lists recurse down
if (lists.length > 1) {
// Use recursion to add all combinations of the remaining lists
combs.addAll(combine(temp, lists.subList(1)));
} else {
// There are no more lists so we are done, add temp to the combos
combs.add(temp);
}
}
return combs;
}
// Call this method to start things going, the other one should probably be private
static <E> ArrayList combine(ArrayList<E>... lists)
return combine(new ArrayList<E>(), lists);
}
Для ленивых (использующих гуаву):
Set<List<String>> result = Sets.cartesianProduct(
ImmutableSet.of("q", "w"),
ImmutableSet.of("a", "s"),
ImmutableSet.of("z", "x")
);
System.out.println(result);
выход:
[
[q, a, z],
[q, a, x],
[q, s, z],
[q, s, x],
[w, a, z],
[w, a, x],
[w, s, z],
[w, s, x]
]
Возможно, вы захотите взглянуть на класс https://github.com/javagl/Combinatorics/blob/master/src/main/java/de/javagl/utils/math/combinatorics/MixedRangeCombinationIterable.java ("автономный"). класс, просто скопируйте и вставьте в свой проект)
Пример использования:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Combinations
{
public static void main(String[] args)
{
List<List<Character>> lists = new ArrayList<List<Character>>();
lists.add(Arrays.asList('q','w'));
lists.add(Arrays.asList('a','s'));
lists.add(Arrays.asList('z','x'));
MixedRangeCombinationIterable<Character> iterable =
new MixedRangeCombinationIterable<Character>(lists);
for (List<Character> element : iterable)
{
System.out.println(element);
}
}
}
Вы фактически вычисляете элементы входных наборов http://en.wikipedia.org/wiki/Cartesian_product
Вверх вы можете создать внутренний класс с помощью конструктора (параметры...), так что вы можете поместить список этого класса, который обрабатывает все комбинации