问题
Say I have the following class:
class A {
String name;
Double value;
}
and a list of the above class objects which might have:
[{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
all I want is to do the followings:
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}]
Can anybody suggest me please how can I do this in Java(with some sample code if possible).
Thanks!
回答1:
Note power sets get large quickly, so this will run out of memory for even fairly small inputs. However if you have the memory, there are no other restrictions.
// 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();
}
}
回答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 ) );
来源:https://stackoverflow.com/questions/11021594/how-to-make-all-possible-power-setor-subset-from-arraylist-objects