I have a list:
a = range(2)
and I am trying to get the list's contents binned into n(=3) bins, in all possible ways, giving (order not important):
[[[],[0],[1]],
[[],[1],[0]],
[[],[0,1],[]],
[[],[],[0,1]],
[[0],[1],[]],
[[0],[],[1]],
[[1],[0],[]],
[[1],[],[0]],
[[0,1],[],[]]]
So far, I have been using the sympy.utilities.iterables
library, firstly to get all possible subsets and filtering the outputs from the variations
method to get the required result:
def binner(a,n=3):
import numpy as np
import sympy.utilities.iterables as itt
import itertools as it
b = list(itt.subsets(a)) #get all subsets
b.append(()) #append empty tuple to allow two empty bins
c=list(itt.variations(b,n))
d=[]
for x in c:
if np.sum(np.bincount(list(it.chain.from_iterable(x))))==len(a):
d.append(x) # add only combinations with no repeats and with all included
return list(set(d)) # remove duplicates
I have a feeling that there is a much better way of doing this. Can anyone help?
Note, I am not tied to the sympy
library and am open to any python/numpy based alternatives.
Assuming I understand your aim (not sure what you might want to happen in cases of duplicate elements, namely whether you want to consider them distinct or not), you could use itertools.product
:
import itertools
def everywhere(seq, width):
for locs in itertools.product(range(width), repeat=len(seq)):
output = [[] for _ in range(width)]
for elem, loc in zip(seq, locs):
output[loc].append(elem)
yield output
which gives
>>> for x in everywhere(list(range(2)), 3):
... print(x)
...
[[0, 1], [], []]
[[0], [1], []]
[[0], [], [1]]
[[1], [0], []]
[[], [0, 1], []]
[[], [0], [1]]
[[1], [], [0]]
[[], [1], [0]]
[[], [], [0, 1]]