Split '000111010010111' into ['000','111','0',1','00','1','0','111']

Viewed 132

Is there some concise way to split up a string of 0s and 1s into the homogeneous, contiguous segments of all 0s and all 1s? Example in the title.

I can of course do it with a nested loop, conditionals, and the .count() method, but this seems like something there'd be a library function for. I'm just not sure how to search for it if there is.

3 Answers

Yes you can using itertools.groupby

from itertools import groupby
a = "000111010010111"
result = ["".join(list(group)) for key, group in groupby(a)]

What happened? We used itertools.groupby to group consecutive terms. A new group is created every time the key element changes (which is when a 0 turns into a 1 or a 1 turns into a 0 in your example). The inner lists are then joined to arrive at your desired output.

Output:

['000', '111', '0', '1', '00', '1', '0', '111']

This will work for any string (not just 1s and 0s) and will group items together based on their consecutive appearances.

This is a quick way of doing it with a generator function, easy to read and understand no cleverness involved.

def split_me(s):
    temp=s[0]
    last=s[0]
    for l in s[1:]:
        if l==last:
            temp+=l
        else:
            yield temp
            temp=l
        last=l
    yield temp 

print(list(split_me('000111010010111')))

From the docs for re.split:

If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list

s = '000111010010111'
list(filter(None, re.split('(0+)', s)))
# ['000', '111', '0', '1', '00', '1', '0', '111']

s2 = '111110110110'
list(filter(None, re.split('(0+)', s)))
# ['11111', '0', '11', '0', '11', '0']

The filter removes empty groups at the beginning or end of the list

Related