如何从ArrayList中对象的所有可能的力量集合(或子集)?(how to make all po

2019-09-18 02:53发布

说我有下面的类:

class A {
    String name;
    Double value;
}

和上面的类对象的列表可能有:

[{f  2.1}, {c  1.1}, {a  0.3}... and so on]
[{n  0.5}, {f  1.9}, {x  0.1}, {a  1.9}, {b  1.1}... and so on]
... and so on

我要的是做如下:

1. Building power subsets from the internal list items(N.B: skip the single subsets).
2. Push the subset in another List as an object of the above class A like this:
    a. if f,c is a subset of 1st element then f,c would be the name property of class A
       and the value property will be the minimum of f and c from the list. 
       Like: {f,c  1.1} [ where f,c is a subset and min of 2.1(value of f) 
       and 1.1(value of c) is 1.1]

so, from the above list if I take 1st element the subsets and their values
in the pushing list would be like this(after skipping the single subsets):
[{f,c  1.1}, {c,a  0.3}, {f,a  0.3}, {f,c,a  0.3}]

and for the 2nd element this would be:

[{n,f  0.5}, {f,x  0.1}, {x,a  0.1}, {a,b  1.1}, {n,x  0.1}, {n,a  0.5}, {n,b  0.5},
{f,a  1.9}, {f,b  1.1}, {x,b  0.1}, {n,f,x   0.1}, {n,x,a  0.1}, 
{n,a,b  0.5}, {f,x,a  0.1}, {f,x,b  0.1}, {x,a,b  0.1}, {n,f,x,a  0.1}, 
{n,f,x,b  0.1}, {n,f,a,b  0.5}, {n,x,a,b  0.1}, {f,x,a,b   0.1}, 
{n,f,x,a,b  0.1}]

有人建议我请我怎么能做到这一点在Java中(有可能的话一些示例代码)。

谢谢!

Answer 1:

注意发电机组获得大快,所以这将耗尽内存甚至相当小的投入。 但是,如果你有记忆,有没有其他限制。

// As stated.
class A {
    String name;
    double value;

    A(String name, double value) {
        this.name = name;
        this.value = value;
    }
}

// Powerset set.
class ASet {
    final ArrayList<String> names = new ArrayList<String>();
    double value = Double.MAX_VALUE;

    void adjoin(A a) {
        names.add(a.name);
        value = Math.min(value, a.value);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('{');
        for (String name : names) {
            sb.append(name);
            sb.append(',');
        }
        sb.append(value);
        sb.append('}');
        return sb.toString();
    }
}

// Make power sets.
class PowerSetFactory {

    // Stack for intermediate results.
    final ArrayDeque<A> stack = new ArrayDeque<A>();

    // Source data.
    ArrayList<A> src;

    // Powerset under construction
    ArrayList<ASet> dst;

    // Recursive powerset calculator
    private void recur(int i) {
        if (i >= src.size()) {
            // Stack is complete. If more than 1 element,
            // add its contents to the result.
            if (stack.size() > 1) {
                ASet set = new ASet();
                for (A a : stack) set.adjoin(a);
                dst.add(set);
            }
        }
        else {
            // Otherwise recur both without and with this element
            // added to the stack.  Clean up the stack before return.
            recur(i + 1);
            stack.offerLast(src.get(i));
            recur(i + 1);
            stack.pollLast();
        }
    }

    // Get a powerset for the givens source data.
    ArrayList<ASet> getPowerSet(ArrayList<A> src) {
        this.src = src;
        this.dst = new ArrayList<ASet>();
        recur(0);
        return dst;
    }

    public void test() {
        ArrayList<A> data = new ArrayList<A>();
        data.add(new A("f", 2.1));
        data.add(new A("c", 1.1));
        data.add(new A("a", 0.3));
        for (ASet set : getPowerSet(data)) {
            System.out.print(set);
        }
        System.out.println();

        data.clear();
        data.add(new A("n", 0.5)); 
        data.add(new A("f",  1.9)); 
        data.add(new A("x",  0.1)); 
        data.add(new A("a",  1.9)); 
        data.add(new A("b",  1.1));
        for (ASet set : getPowerSet(data)) {
            System.out.print(set);
        }
        System.out.println();
    }
}


Answer 2:

I am assuming that the order of the subsets on each element of your output list is irrelevant.

For inputs of any significant size, your output will be intractably large, so don't try to keep it in memory. You're better off implementing PowerList as its own collection. The following draft will only work for inputs of length 31 or less, and does not filter the singletons or the empty list.

public class PowerList extends AbstractList< A > {
    private final List< A > laUnderlying;
    public PowerList( List< A > laUnderlying ) {
        this.laUnderlying = laUnderlying;
    }
    @Override
    public A get( int index ) {
        StringBuilder sbLabel;
        A aOut = new A();
        aOut.value = Double.MAX_VALUE;
        int iUnderIndex = 0;
        while ( 0 < index ) {
            while ( 0 == ( index & 1 ) ) {
                ++iUnderIndex;
                index = index >> 1;
            }
            A aComponent = laUnderlying.get( index );
            sbLabel.append( ',' ).append( aComponent.name );
            if ( aComponent.value < aOut.value )
                aOut.value = aComponent.value;
        }
        if ( !sbLabel.isEmpty() )
            aOut.name = sbLabel.substring( 1 );
        return aOut;
    }
    public int size() {
        return 1 << laUnderlying.size();
    }
}

Now your original question reduces to

List< List< A > > llaOutput;
for ( List< A > laEach : llaInput )
    llaOutput.add( new PowerList( laEach ) );


文章来源: how to make all possible power set(or subset) from arrayList objects?