Python Combinations
<p>Suppose I have a Python list that looks like:</p>

<pre><code>[1, 2, 3, 4]
</code></pre>

<p>I would like to be able to return a list of lists containing all combinations of two or more numbers. The order of the values doesn't matter so 1,2 is the same as 2,1.  I would also like to return another list that contains the values that do not feature in each combination. For example:</p>

<pre><code>Combination 1,2 / Remainder 3,4
Combination 2,3 / Remainder 1,4
Combination 1,2,3 / Remainder 4
Combination 1,2,3,4/ Remainder -
</code></pre>

<p>The returned lists for the above would be</p>

<pre><code>combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]]
remainder = [[3,4], [1,4], [4], []]
</code></pre>

<p>I've only shown a few examples...</p>

<p>I realise that the first part can probably be achieved using <code>itertools.combinations</code> but how can I return those values not used in the combination without looping?</p>

<p>Building upon the idea by <a href="http://stackoverflow.com/a/39545624/1639625">Nunzio</a>, but instead of converting numbers in a certain range to binary, you can just use <code>itertools.product</code> to get all combinations of <code>1</code> and <code>0</code> (or <code>True</code> and <code>False</code>) and then use that as a mask for filtering the "ins" and "outs".</p>

<pre><code>&gt;&gt;&gt; lst = [1,2,3]
&gt;&gt;&gt; products = list(product([1,0], repeat=len(lst)))
&gt;&gt;&gt; [[lst[i] for i, e in enumerate(p) if e] for p in products]
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
&gt;&gt;&gt; [[lst[i] for i, e in enumerate(p) if not e] for p in products]
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]
</code></pre>

<p>You could also define a function for that <code>enumerate</code> comprehension and do both parts in one go:</p>

<pre><code>&gt;&gt;&gt; mask = lambda lst, p, v: [lst[i] for i, e in enumerate(p) if e == v]
&gt;&gt;&gt; [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0], repeat=len(lst))]
[([1, 2, 3], []),
 ([1, 2], [3]),
 ([1, 3], [2]),
 ([1], [2, 3]),
 ([2, 3], [1]),
 ([2], [1, 3]),
 ([3], [1, 2]),
 ([], [1, 2, 3])]
</code></pre>

<p>If you only want combinations with 2 or more in the "in" list, you can add a condition:</p>

<pre><code>&gt;&gt;&gt; [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0],repeat=len(lst)) if sum(p) &gt;= 2]
</code></pre>

<p>Or use <code>numpy</code> arrays and make use of <code>numpy</code>'s advanced indexing:</p>

<pre><code>&gt;&gt;&gt; arr = np.array([1,2,3])
&gt;&gt;&gt; [(arr[p==1], arr[p==0]) for p in map(np.array, product([1,0], repeat=len(arr)))]
[(array([1, 2, 3]), array([])),
 (array([1, 2]), array([3])),
 (array([1, 3]), array([2])),
 (array([1]), array([2, 3])),
 (array([2, 3]), array([1])),
 (array([2]), array([1, 3])),
 (array([3]), array([1, 2])),
 (array([]), array([1, 2, 3]))]
</code></pre>

python python-2.7 combinations itertools