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?

+3


source to share


3 answers


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]]

      

+4


source


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

      

+3


source


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)]

      

+1


source







All Articles