Nili Sabbah
Nili Sabbah

Reputation: 33

How to split a string to sequences of odd numbers?

I'm trying to find a way to split a number to list of odd number sequences:

num = "57483795478973"

for digit in num:
    if int(digit)%2==0:
        list_a = str.split(num,digit)

print (list_a)

but the result I'm getting is

['574', '379547', '973']

which includes the even numbers, and I don't understand what I'm doing wrong.

Upvotes: 1

Views: 899

Answers (4)

BartoszKP
BartoszKP

Reputation: 35901

Here is a solution using the re module:

>>> import re
>>> re.split('[02468]', '57483795478973')
['57', '', '3795', '7', '973']

The first argument, in this case, is effectively a list of delimiters - which are even numbers in your case. If you want to skip empty results:

>>>[r for r in re.split('[02468]', '57483795478973') if r]
['57', '3795', '7', '973']

And here is a way to calculate it by hand, using a generator:

def splitToOddSeqs(numbers):
    seq = ""
    for n in numbers:
        if n not in "02468":
            seq += n      # as long as we have odd numbers, we accumulate
        else:
            if seq:
                yield seq # we've found an even number - return one sequence
                seq = ""

    if seq:
        yield seq         # return last one (when input ends with odd digit)

Example usage:

>>> list(splitToOddSeqs('57483795478973'))
['57', '3795', '7', '973']

Upvotes: 5

japreiss
japreiss

Reputation: 11251

It sounds like the result you want is:

['57', '3795', '7', '973']

But every iteration through the loop, you replace list_a with the most recent str.split(num, digit). Since 8 is the last even digit in num, the final value of list_a is str.split(num, '8') - a string that's only split on 8's.

Passing your output through split over and over again won't work either, because after the first split, you're working with a list of strings instead of a single string.

I'm surprised Python doesn't provide a library function that splits on any of a set of characters. Looks like you'll need to write it yourself.

Also, your code does extra work by looping over the digits in num instead of just looping over all the even digits once. If num is very long, you'll end up splitting on the same digit over and over, wasting effort.

I wrote a less Pythonic, more C-like answer, but I like the answers using regex, itertools, and generators better.

Upvotes: 0

Kasravnd
Kasravnd

Reputation: 107347

Alongside the other good answers , you can use itertools.groupby (good if you are consider about performance ):

>>> import itertools
>>> l=[list(g) for k,g in itertools.groupby(num,lambda x : int(x)%2==0)]
>>> [''.join(i) for i in l if int(i[0])%2!=0]
['57', '3795', '7', '973']

Upvotes: 1

Brent Washburne
Brent Washburne

Reputation: 13158

You're calculating list_a every time through the loop. The final time through the loop ('8') gives the result that you see. What you want is to split on '0', '2', '4' and '6' as well as '8'.

Upvotes: 1

Related Questions