Python-related list item combinations
I have a list of values [1,2,3,4,5,...]
, I want to return a list of all possible related combinations using lists, numpy or whatever.
By connecting, I mean that pairs of items in a list must maintain their contiguity in combinations (it is not necessary for integers with adjacent values to be next to each other, although that would be fine).
To be clear, here's what I would like to return, in the case of a list [1,2,3,4,5]
:
[[1,2,3,4,5],
[1,2,3,4],
[2,3,4,5],
[1,2,3],
[2,3,4],
[3,4,5],
[1,2],
[2,3],
[3,4],
[4,5],
[1],
[2],
[3],
[4],
[5]]
And here are the types of elements I do not :
[[1,2,3,5],
[1,3,4,5],
...]
I have seen many posts about getting all possible combinations in general, but I have not seen anyone ask a question about constrained combinations. Any ideas?
source to share
Here's a way with a list:
>>> lst = [6, 7, 8, 9]
>>> [lst[i:j] for j in range(len(lst)+1) for i in range(j)]
[[6], [6, 7], [7], [6, 7, 8], [7, 8], [8], [6, 7, 8, 9], [7, 8, 9], [8, 9], [9]]
Or, if you are evaluating the order, and if I am guessing it correctly from your example:
>>> [lst[i:i+leng] for leng in range(len(lst), 0, -1) for i in range(len(lst)-leng+1)]
[[6, 7, 8, 9], [6, 7, 8], [7, 8, 9], [6, 7], [7, 8], [8, 9], [6], [7], [8], [9]]
Or with itertools.combinations
:
>>> [lst[i:j] for i, j in combinations(range(len(lst)+1), 2)]
[[6], [6, 7], [6, 7, 8], [6, 7, 8, 9], [7], [7, 8], [7, 8, 9], [8], [8, 9], [9]]
Or even without any kind of list comprehension (but now I'm getting stupid :-)
>>> list(map(lst.__getitem__, starmap(slice, combinations(range(len(lst)+1), 2))))
[[6], [6, 7], [6, 7, 8], [6, 7, 8, 9], [7], [7, 8], [7, 8, 9], [8], [8, 9], [9]]
source to share
from itertools import islice
def adj(l):
ln = len(l)
yield l
for n in range(ln -1, 0, -1):
yield from (list(islice(l, i, n + i)) for i in range(ln - n % ln+1))
l = [1, 2, 3, 4, 5]
print(list(adj(l)))
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3], [2, 3, 4], [3, 4, 5], [1, 2], [2, 3], [3, 4], [4, 5], [1], [2], [3], [4], [5]]
You can get the value at the same time without having to keep all the elements in memory:
def adj(l):
ln = len(l)
yield l
for n in range(ln - 1, 0, -1):
yield from (islice(l, i, n + i) for i in range(ln - n % ln+1))
l = [1, 2, 3, 4, 5]
for ele in adj(l):
print(list(ele))
Output:
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[2, 3, 4, 5]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[1, 2]
[2, 3]
[3, 4]
[4, 5]
[1]
[2]
[3]
[4]
[5]
Or call a function on each chunk:
for ele in adj(l):
print(sum(ele))
Output:
15 10 14 6 9 12 3 5 7 9 1 2 3 4 5
source to share
I'm sure there are many ways to do this. I propose a simple function that couldn't be a more pythonic solution.
def c_list(A):
B = []
for i in range(len(A)):
for j in range(len(A) - i):
B.append(A[j:j+i+1])
return B
A = [ 1,2,3,4,5 ]
B = c_list(A)
print B
This strategy can be used with list comprehension if that's your thing:
C = [A[j:j+i+1] for i in range(len(A)) for j in range(len(A)-i)]
source to share