micgeronimo
micgeronimo

Reputation: 2149

Split string of digits into lists of even and odd integers

Having such code

numbers = '1 2 3 4 5 6 7 8'
nums = {'evens': [], 'odds': []}

for number in numbers.split(' '):
    if int(number) % 2:
        nums['odds'].append(number)
    else:
        nums['evens'].append(number)

How can accomplish same on fewer lines?

Upvotes: 6

Views: 4800

Answers (6)

Iron Fist
Iron Fist

Reputation: 10951

You can accomplish the same results with itertools.groupby, like so:

>>> from itertools import groupby
>>>
>>> numbers = '1 2 3 4 5 6 7 8'
>>> d = {'even':[], 'odd':[]}
>>> mynum = [int(x) for x in numbers.strip().split()]
>>> for k,g in groupby(mynum, lambda x: x % 2):
        if k:
            d['odd'].extend(g)
        else:
            d['even'].extend(g)


>>> d
{'even': [2, 4, 6, 8], 'odd': [1, 3, 5, 7]}

Upvotes: 4

Will
Will

Reputation: 24709

Short code is not better code. Short code is not faster code. Short code is not maintainable code. Now, that said, it is good to make your individual components concise and simple.

Here's what I would do:

def split_odd_even(number_list):
    return {
        'odds': filter(lambda n: (n % 2) != 0, number_list),
        'evens': filter(lambda n: (n % 2) == 0, number_list)
    }

def string_to_ints(string):
    return map(int, numbers.strip().split())

numbers = '1 2 3 4 5 6 7 8 9 10'
nums = split_odd_even(string_to_ints(numbers))

print nums

This gives me:

{'odds': [1, 3, 5, 7, 9], 'evens': [2, 4, 6, 8, 10]}

While this code has actually added a few lines in length, it has become much more clear what the program is doing, as we've applied Abstraction and made each component of the code do only one thing well.

Even though we've added two functions, the most-visible part of the code has gone from this:

numbers = '1 2 3 4 5 6 7 8'
nums = {'evens': [], 'odds': []}
for number in numbers.split(' '):
    if int(number) % 2:
        nums['odds'].append(number)
    else:
        nums['evens'].append(number)

To this:

numbers = '1 2 3 4 5 6 7 8 9 10'
nums = split_odd_even(string_to_ints(numbers))

And just by reading these two lines, we know that numbers is converted from a string to a list of ints, and that we then split those numbers into odd and even, and assign the result to nums.

To explain a a couple of things that may not be familiar to all:

  • map() calls a function for every item in a list (or tuple or other iterable), and returns a new list with the result of the function being called on each item. In this case, we use it to call int() on each item in the list.

  • filter() calls a function for every item in a list (or tuple or other iterable), which returns True or False for each item (well, truthy or falsey), and returns a list of items that evaluated to True when the function is called.

  • Lambda Expressions (lambda) are like "mini-functions" that take arguments and can be created in-place.

Upvotes: 6

Netwave
Netwave

Reputation: 42756

A functional aproach:

>>> numbers = '1 2 3 4 5 6 7 8'
>>> numbers = map(int, numbers.split())
>>> nums = {'evens': filter(lambda x: x%2 == 0, numbers), 'odds': filter(lambda x: x%2 != 0, numbers)}
>>> nums
{'evens': [2, 4, 6, 8], 'odds': [1, 3, 5, 7]}

Upvotes: 4

Aran-Fey
Aran-Fey

Reputation: 43276

You can do it as a one-liner, but I wouldn't recommend it. Your code is perfectly fine.

[nums['odds'].append(n) if int(n)%2 else nums['evens'].append(n) for n in numbers.split(' ')]

Upvotes: 0

RvdK
RvdK

Reputation: 19800

If you just want to try it out:

numbers = '1 2 3 4 5 6 7 8'
nums = {'evens': [], 'odds': []}
for number in numbers.split(' '):
    category = 'odds' if int(number) % 2 else 'evens'
    nums[category].append(number)

But if you want to use it in production: Readable code is more important than 'short' code

Upvotes: 1

user5547025
user5547025

Reputation:

numbers = '1 2 3 4 5 6 7 8'
nums = {}
nums["even"] = [int(i) for i in numbers.split() if int(i) % 2 == 0]
nums["odd"] = [int(i) for i in numbers.split() if int(i) % 2 == 1]
print(nums)

Output:

{'even': [2, 4, 6, 8], 'odd': [1, 3, 5, 7]}

Upvotes: 1

Related Questions