Reputation: 3469
As a beginner computer science student I was assigned to write a function to sort a list of even and odd numbers into two sublists. Wait... don't down vote me. I have been learning on my own a bit and experimenting with list comprehension and timeit and was wondering if I could recreate this with list comprehension to do something a bit more challenging instead.
I've figured out how to use list comprehension to flatten sublists, but not the other way around. Is it possible?
def odd_even_filter(numbers):
even = []
odd = []
for i in numbers:
if i % 2 == 0:
even.append(i)
else:
odd.append(i)
return [even, odd]
odd_even_filter([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>[[2,4,6,7],[1,3,5,7,9]]
Just trying to see if i can take a flat list and generate nested lists using list comprehension. It may not be worth it and not the python way, but just experimenting.
Upvotes: 3
Views: 1030
Reputation: 9224
If you're aiming for the shortest, yet pythonic answer, How about?
odd = [i for i in numbers if i % 2] # this is O(n)
even = list(set(numbers) - set(odd)) # this is O(n log n)
An inefficient, but still clear alternative is:
even = numbers - odd # this is O(n^2)
An O(n) alternative (the best?) would be:
odd = [i for i in numbers if i % 2] # this is O(n)
even = [i for i in numbers if not i % 2] # this is O(n)
Upvotes: 2
Reputation: 4184
Based on ssm's post:
>>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [list(filter(lambda x: x%2==0, l)), list(filter(lambda x: x%2==1, l))]
[[2, 4, 6, 8], [1, 3, 5, 7, 9]]
This solution is slow though.
Upvotes: 0
Reputation: 16940
if your number are in sequence you can even use slice:
>>> [r[1::2],r[2::2]]
[[1, 3, 5, 7, 9], [2, 4, 6, 8]]
>>>
Upvotes: 0
Reputation: 5373
There is always a tradeoff between readability and compactness in code. In this case, I believe the answer by devnull is excellent. He uses list comprehensions and Python if
expression resulting in something very readable in a single line. If your test criterion is more stringent, it is generally more useful to separate out the conditions into their own functions. For your example, these would be:
def even(x): return x%2 == 0
def odd(x) : return x%2 != 0
and then use them for filtering out the results like so:
def oddEvenFilter(x): return [filter(even, x), filter(odd, x)]
These are three lines of code, but in combination is very readable.
Upvotes: 1
Reputation: 3469
This works, not easier to read at all, but it is possible with range being the number of subgroups, 2 for even and odd.
return [[ n for n in numbers if n % 2 == 0] if i == 0 else [ n for n in numbers if n % 2 != 0] for i in range(2)]
Ran this through timeit and it takes twice as long which is to be expected. devnull's answer takes a little bit longer too.
def odd_even_filter(numbers):
even = []
odd = []
for i in numbers:
if i % 2 == 0:
even.append(i)
else:
odd.append(i)
return [even, odd]
def odd_even_filter_2(numbers):
return [[ n for n in numbers if n % 2 == 0] if i == 0 else [ n for n in numbers if n % 2 != 0] for i in range(2)]
def odd_even_filter_3(numbers):
even = []
odd = []
[ odd.append(n) if n % 2 != 0 else even.append(n) for n in numbers]
return [even,odd]
print(timeit.timeit('odd_even_filter([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter" ))
print(timeit.timeit('odd_even_filter_2([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter_2" ))
print(timeit.timeit('odd_even_filter_3([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter_3" ))
>>2.2804439414858675
>>4.190625469924679
>>3.0541580641135733
Upvotes: 0