Milano
Milano

Reputation: 18745

Get all combinations of neighbour elements in list

Is it possible to get all combinations of elements in case they are neighbours?
Here is the example:

EDIT: I want to use it on strings, not only numbers. For example: [Explain,it,to,me,please]

List:

[0,1,2,3,4]

Result:

[0,1,2,3,4],
[0,1,2,3],
[1,2,3,4],
[0,1,2],
[1,2,3],
[2,3,4],
[0,1],
[1,2],
[2,3],
[3,4],
[0],
[1],
[2],
[3],
[4]

There wouldn't be for example [0,2,3] etc. in the result because 0 and 2 are not neighbours in the sorted list above.

I tried to use itertools.combinations but it gives all combinations.

Upvotes: 5

Views: 1681

Answers (3)

Daenyth
Daenyth

Reputation: 37461

Here's one way using an old window recipe from itertools

from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result    
    for elem in it:
        result = result[1:] + (elem,)
        yield result

def all_windows(seq):
    for l in xrange(1, len(seq) + 1):
        for w in window(seq, l):
            yield w

Upvotes: 2

Prashant Kumar
Prashant Kumar

Reputation: 22589

Much like cpburnz answer, this does it with a nested list comprehension.
The difference is, the lists are generated sorted in length order, largest to smallest.

[L[j:i+j] for i in xrange(len(L), 0, -1) for j in xrange(len(L) - i + 1)]

However, if you just need to generate the lists, then consider writing a bit more readable code using a generator:

def all_windows(L):
    for i in xrange(len(L), 0, -1):
        for j in xrange(len(L) - i + 1):
            yield L[j:i+j]

Same code as above, but designed to be iterated through:

for sublist in all_windows(L):
    # does something with sublist

Upvotes: 0

ohmu
ohmu

Reputation: 19780

You can do:

>>> L = [0,1,2,3,4]
>>> result = [L[i:j] for i in xrange(len(L)) for j in xrange(i + 1, len(L) + 1)]
>>> pprint.pprint(result)
[[0],
 [0, 1],
 [0, 1, 2],
 [0, 1, 2, 3],
 [0, 1, 2, 3, 4],
 [1],
 [1, 2],
 [1, 2, 3],
 [1, 2, 3, 4],
 [2],
 [2, 3],
 [2, 3, 4],
 [3],
 [3, 4],
 [4]]

Then, to sort by descending length and ascending values:

>>> result.sort(key=lambda x: (-len(x), x))
>>> pprint.pprint(result)
[[0, 1, 2, 3, 4],
 [0, 1, 2, 3],
 [1, 2, 3, 4],
 [0, 1, 2],
 [1, 2, 3],
 [2, 3, 4],
 [0, 1],
 [1, 2],
 [2, 3],
 [3, 4],
 [0],
 [1],
 [2],
 [3],
 [4]]

And for strings it would produce:

>>> L = ['Explain', 'it', 'to', 'me', 'please']
>>> result = [L[i:j] for i in xrange(len(L)) for j in xrange(i + 1, len(L) + 1)]
>>> result.sort(key=lambda x: (-len(x), x))
>>> pprint.pprint(result)
[['Explain', 'it', 'to', 'me', 'please'],
 ['Explain', 'it', 'to', 'me'],
 ['it', 'to', 'me', 'please'],
 ['Explain', 'it', 'to'],
 ['it', 'to', 'me'],
 ['to', 'me', 'please'],
 ['Explain', 'it'],
 ['it', 'to'],
 ['me', 'please'],
 ['to', 'me'],
 ['Explain'],
 ['it'],
 ['me'],
 ['please'],
 ['to']]

Upvotes: 9

Related Questions