属性值的组合

时间:2018-10-15 06:42:28

标签: java recursion arraylist hashmap

我很努力地生成属性列表的所有可能值组合。例如,对于具有以下值的三个属性A,B,C:A的{a1,a2},B的{b1,b2}和C的{c1,c2},我应该得到8种组合: / p>

a1,b1,c1
a1,b1,c2
a1,b2,c1
a1,b2,c2
a2,b1,c1
a2,b1,c2
a2,b2,c1
a2,b2,c2

我使用了以下两个递归Java函数,其中attribute_to_domainMap,在其中我们将每个属性都设为key,并将其值都设为value,然后添加每个组合作为<ArrayList<String>enumerate_tuples作为ArrayList<ArrayList<String>>

    public  void fillTuples(Map<String, Set<String>> attribute_to_domain, ArrayList<String> attributes, ArrayList<ArrayList<String>> enumerate_tuples)
{      
        for (Map.Entry<String, Set<String>> entrySet :attribute_to_domain.entrySet()) {
         String attribute=entrySet.getKey();
         attributes.add(attribute);
        }
    int pos = 0;
    Set<String> domain = attribute_to_domain.get(attributes.get(pos));
        for (Iterator<String> it = domain.iterator(); it.hasNext();) {
               String val = it.next();
            ArrayList<String> tuple=new ArrayList<String>();
            tuple.add(val);
                fillTuples(attribute_to_domain, attributes, 1, tuple, enumerate_tuples);
          tuple.remove(tuple.size()-1);
          assert(tuple.isEmpty());
          }

      }
public  void fillTuples(Map<String, Set<String>> attribute_to_domain, ArrayList<String> attributes, int pos, ArrayList<String> tuple,  ArrayList<ArrayList<String>>  enumerate_tuples)
{                              
    assert(tuple.size() == pos);
    if (pos == attributes.size())
    {      
       enumerate_tuples.add(tuple);
       return;
    }

        Set<String> domain = attribute_to_domain.get(attributes.get(pos));
        for (Iterator<String> it = domain.iterator(); it.hasNext();) {
          String val = it.next();
          tuple.add(val);
          fillTuples(attribute_to_domain, attributes, pos+1, tuple, enumerate_tuples);
          tuple.remove(tuple.size()-1);
        }

}

我得到enumerate_tuples带有空元素的问题,我无法通过调用保留发生在其上的更改。

请问如何解决这个问题?预先感谢。

2 个答案:

答案 0 :(得分:1)

有一种更简单,更快速的解决方案,不需要递归。

可以高级地计算输出组合的数量:在您的情况2*2*2中属性的相乘,但是每种组合都适用。

此外,我们可以基于组合索引来计算将在每个组合中放置哪个值。如果我们假设组合索引从0到7:
A
-组合0-3将包含a1
-组合4-7将包含a2
B
-组合0、1、4、5将包含b1
-组合2、3、6、7将包含b2
C
-组合0、2、4、6将包含c1
-组合1,3,5,7将包含c2

因此,值放置的公式基于组合索引,属性的顺序(首先为A等)和属性中值的顺序。

该算法的复杂度为o(n * m),其中n是属性数,m是值。

答案 1 :(得分:0)

修订自Cartesian product of arbitrary sets in Java

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class CartesianProduct {

    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 TreeSet<Set<Object> >(new Comparator<Set<Object> >() {
            @Override
            public int compare(Set<Object> o1, Set<Object> o2) {
                return o1.toString().compareTo(o2.toString());
            }
        });

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

    public static void main(String[] args) {
        Map<String, Set<String> > dataMap = new HashMap<String, Set<String> >();
        dataMap.put("A", new TreeSet<String>(Arrays.asList("a1", "a2")));
        dataMap.put("B", new TreeSet<String>(Arrays.asList("b1", "b2")));
        dataMap.put("C", new TreeSet<String>(Arrays.asList("c1", "c2")));

        System.out.println(cartesianProduct(dataMap.values().toArray(new Set<?>[0])));
    }

}