我正在寻找一个可以生成这样的矢量组合的Java库:
假设:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape>
<gradient
android:startColor="#ffffff"
android:endColor="#ffffff"
android:angle="270" />
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:endColor="#ffffff"
android:startColor="#ffffff"
android:angle="270" />
</shape>
</item>
<item>
<shape>
<gradient
android:endColor="#ffffff"
android:startColor="#ffffff"
android:angle="270" />
</shape>
</item>
</selector>
产生以下组合:
vector1 = {A, B, C}
vector2 = {0, 1, 2}
向量的数量给出了维度的数量(组合的列)。
在Python中,来自A, 0
A, 1
A, 2
B, 0
B, 1
B, 2
C, 0
C, 1
C, 2
库的函数product
正是这样做的,但我还没有看到任何Java库。
感谢。
答案 0 :(得分:1)
您可以使用java8流来完成它,就像从库中调用函数一样简单。假设你已经拥有:
List<String> vector1 = Arrays.asList("A","B","C");
List<Integer> vector2 = Arrays.asList(1,2,3);
您可以通过以下方式获得预期结果
Map<String, Integer> result = new HashMap<>();
vector1.stream().forEach(o1 -> vector2.stream().forEach(o2 -> result.put(o1,o2)));
或者,如果您更喜欢List of Tuples,那么您需要为对创建一个类,或者使用Tuple
答案 1 :(得分:1)
解决方案#1 :您可以使用地图将字符串与整数列表相关联。
public static void main(String[] args) {
List<String> v1 = Arrays.asList("A", "B", "C");
List<Integer> v2 = Arrays.asList(0, 1, 2);
Map<String, List<Integer>> product = getProduct(v1, v2);
}
public static Map<String, List<Integer>> getProduct(List<String> v1, List<Integer> v2) {
Map<String, List<Integer>> product = new HashMap<>();
for (String e1 : v1) {
product.put(e1, v2);
}
return product;
}
数据以这种方式表示:
解决方案#2 :您创建了Combination
个对象的列表。
public class Combination<T1, T2> {
protected final T1 value1;
protected final T2 value2;
public Combination(T1 value1, T2 value2) {
this.value1 = value1;
this.value2 = value2;
}
public T1 getValue1() {
return value1;
}
public T2 getValue2() {
return value2;
}
}
public class CombinationGenerator<T1, T2> {
protected final List<T1> values1;
protected final List<T2> values2;
public CombinationGenerator(List<T1> values1, List<T2> values2) {
this.values1 = values1;
this.values2 = values2;
}
public List<Combination<T1, T2>> getCombinations() {
List<Combination<T1, T2>> combinations = new LinkedList<>();
for (T1 e1 : values1) {
for (T2 e2 : values2) {
combinations.add(new Combination<>(e1, e2));
}
}
return combinations;
}
}
public static void main(String[] args) {
List<String> v1 = Arrays.asList("A", "B", "C");
List<Integer> v2 = Arrays.asList(0, 1, 2);
CombinationGenerator<String, Integer> combGen = new CombinationGenerator<>(v1, v2);
List<Combination<String, Integer>> combinations = combGen.getCombinations();
}
此解决方案返回9种组合的列表:
修改:对于解决方案#1,您可以使用Guava的Multimap
public static Multimap<String, Integer> getCombinations(List<String> v1, List<Integer> v2) {
Multimap<String, Integer> combinations = ArrayListMultimap.create();
for (String e1 : v1) {
for (Integer e2 : v2) {
combinations.put(e1, e2);
}
}
return combinations;
}
答案 2 :(得分:0)
之前给出的答案很好但不适用于N维。
This代码是可推广的,也是正确的。
/*
* www.javagl.de - Utilities - Combinatorics
*
* Copyright (c) 2008-2013 Marco Hutter - http://www.javagl.de
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package de.javagl.utils.math.combinatorics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* A class providing an iterator over all combinations of a certain number
* of elements, where the valid ranges may be different for each element
* of the combination. For a set S = { S0, S1, ... Sn } there will be
* |S0| * |S1| * ... * |Sn| possible combinations. Example:<br />
* <pre>
* S0 = {A,B,C}, |S0| = 3
* S1 = {D,E} , |S1| = 2
* S2 = {A,E} , |S2| = 2
* S = { S0, S1, S2 }
* m = |S0| * |S1| * |S0| = 3 * 2 * 2 = 12 combinations
*
* Combinations:
* [A, D, A]
* [A, D, E]
* [A, E, A]
* [A, E, E]
* [B, D, A]
* [B, D, E]
* [B, E, A]
* [B, E, E]
* [C, D, A]
* [C, D, E]
* [C, E, A]
* [C, E, E]
* </pre>
*
* @param <T> The type of the elements
*/
public final class MixedRangeCombinationIterable<T> implements Iterable<List<T>>
{
/**
* The input elements
*/
private List<? extends Collection<? extends T>> sets;
/**
* The total number of elements that the iterator will provide
*/
private final int numElements;
/**
* Creates an iterable over all combinations of one element
* of each of the given sets.
*
* @param sets The input sets
*/
public MixedRangeCombinationIterable(
List<? extends Collection<? extends T>> sets)
{
this.sets = sets;
int m = 0;
if (sets.size() > 0)
{
m = 1;
}
for (Collection<? extends T> set : sets)
{
m *= set.size();
}
this.numElements = m;
}
@Override
public Iterator<List<T>> iterator()
{
return new Iterator<List<T>>()
{
/**
* The element counter
*/
private int current = 0;
/**
* The current combination
*/
private List<T> currentCombination = new ArrayList<T>();
/**
* The iterators over the individual sets
*/
private List<Iterator<? extends T>> subIterators =
new ArrayList<Iterator<? extends T>>(
Collections.<Iterator<? extends T>>nCopies(
sets.size(), null));
// Initialize the sub-iterators and the first combination
{
if (numElements > 0)
{
for (int i=0; i<sets.size(); i++)
{
Iterator<? extends T> subIterator =
sets.get(i).iterator();
subIterators.set(i, subIterator);
currentCombination.add(subIterator.next());
}
}
}
@Override
public boolean hasNext()
{
return current < numElements;
}
@Override
public List<T> next()
{
if (!hasNext())
{
throw new NoSuchElementException("No more elements");
}
List<T> result = new ArrayList<T>(currentCombination);
increase(sets.size()-1);
current++;
return result;
}
/**
* Increases the selection of elements by one.
*
* @param index The index to increase
*/
private void increase(int index)
{
if (index < 0)
{
return;
}
Iterator<? extends T> subIterator = subIterators.get(index);
if (subIterator.hasNext())
{
currentCombination.set(index, subIterator.next());
}
else
{
subIterator = sets.get(index).iterator();
subIterators.set(index, subIterator);
currentCombination.set(index, subIterator.next());
increase(index-1);
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException(
"May not remove elements from a combination");
}
};
}
}
典型用法是:
List<List<Integer>> inputs = new ArrayList<List<Integer>>();
input.add(Arrays.asList(0, 1, 2));
input.add(Arrays.asList(0, 1, 2, 3));
input.add(Arrays.asList(0, 1));
MixedRangeCombinationIterable<Integer> product =
new MixedRangeCombinationIterable(inputs)
for(List<Integer> combination: product){
System.out.println(combination)
}
答案 3 :(得分:0)
以下是计算这样的矢量积的类,也称为输入空间的Cartesian Product。它适用于任意数据类型和任意数量的维度。
(原来是I published it on GitHub,但现在它是在通常的stackoverflow许可下发布的)
它在构造函数中接收集合列表。这些集合中的每一个都提供了一个迭代器,用于迭代各自的维度。整个类本身实现为Iterable
(基本上只包装相应的Iterator
类)。在每个时间点,此迭代器仅维护集合的“当前”迭代器列表,并在调用next()
时返回相应的元素并增加迭代器。
这种方法的优点是将整个笛卡尔积保存在内存中不必要。可以迭代一个大于可用物理内存的笛卡尔积(考虑到笛卡尔积很大,这可能很重要)。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* A class providing an iterator over all combinations of a certain number
* of elements, where the valid ranges may be different for each element
* of the combination. For a set S = { S0, S1, ... Sn } there will be
* |S0| * |S1| * ... * |Sn| possible combinations. Example:<br />
* <pre>
* S0 = {A,B,C}, |S0| = 3
* S1 = {D,E} , |S1| = 2
* S2 = {A,E} , |S2| = 2
* S = { S0, S1, S2 }
* m = |S0| * |S1| * |S0| = 3 * 2 * 2 = 12 combinations
*
* Combinations:
* [A, D, A]
* [A, D, E]
* [A, E, A]
* [A, E, E]
* [B, D, A]
* [B, D, E]
* [B, E, A]
* [B, E, E]
* [C, D, A]
* [C, D, E]
* [C, E, A]
* [C, E, E]
* </pre>
*
* @param <T> The type of the elements
*/
public final class MixedRangeCombinationIterable<T> implements Iterable<List<T>>
{
/**
* The input elements
*/
private List<? extends Collection<? extends T>> sets;
/**
* The total number of elements that the iterator will provide
*/
private final int numElements;
/**
* Creates an iterable over all combinations of one element
* of each of the given sets.
*
* @param sets The input sets
*/
public MixedRangeCombinationIterable(
List<? extends Collection<? extends T>> sets)
{
this.sets = sets;
int m = 0;
if (sets.size() > 0)
{
m = 1;
}
for (Collection<? extends T> set : sets)
{
m *= set.size();
}
this.numElements = m;
}
@Override
public Iterator<List<T>> iterator()
{
return new Iterator<List<T>>()
{
/**
* The element counter
*/
private int current = 0;
/**
* The current combination
*/
private List<T> currentCombination = new ArrayList<T>();
/**
* The iterators over the individual sets
*/
private List<Iterator<? extends T>> subIterators =
new ArrayList<Iterator<? extends T>>(
Collections.<Iterator<? extends T>>nCopies(
sets.size(), null));
// Initialize the sub-iterators and the first combination
{
if (numElements > 0)
{
for (int i=0; i<sets.size(); i++)
{
Iterator<? extends T> subIterator =
sets.get(i).iterator();
subIterators.set(i, subIterator);
currentCombination.add(subIterator.next());
}
}
}
@Override
public boolean hasNext()
{
return current < numElements;
}
@Override
public List<T> next()
{
if (!hasNext())
{
throw new NoSuchElementException("No more elements");
}
List<T> result = new ArrayList<T>(currentCombination);
increase(sets.size()-1);
current++;
return result;
}
/**
* Increases the selection of elements by one.
*
* @param index The index to increase
*/
private void increase(int index)
{
if (index < 0)
{
return;
}
Iterator<? extends T> subIterator = subIterators.get(index);
if (subIterator.hasNext())
{
currentCombination.set(index, subIterator.next());
}
else
{
subIterator = sets.get(index).iterator();
subIterators.set(index, subIterator);
currentCombination.set(index, subIterator.next());
increase(index-1);
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException(
"May not remove elements from a combination");
}
};
}
}
此类的用法可能如下所示:
List<List<Integer>> inputs = new ArrayList<List<Integer>>();
input.add(Arrays.asList(0, 1, 2));
input.add(Arrays.asList(0, 1, 2, 3));
input.add(Arrays.asList(0, 1));
MixedRangeCombinationIterable<Integer> product =
new MixedRangeCombinationIterable(inputs)
for(List<Integer> combination: product){
System.out.println(combination)
}