from operator import itemgetter
from itertools import takewhile
xs = [ ('foo',1), ('bar',1), ('baz',2) ]
xs
is sorted on the second item - there are no more 1
s after 'bar'
.
def item_map(xs):
getcount = itemgetter(1)
return list(map(getcount,xs))
print(item_map(xs))
>>> [1, 1, 2]
returns a list of the second element of every tuple.
def item_take(xs):
return list(takewhile(lambda x: x[1] == 1, xs))
print(item_take(xs))
[('foo', 1), ('bar', 1)]
returns the tuples that have a second element that == 1.
def could_this_work(xs):
match = itemgetter(1) == 1
return list(takewhile(match, xs))
print(could_this_work(xs))
TypeError: 'bool' object is not callable
does not return the tuples that have a second element that == 1
Is there a way to use itemgetter
in place of the lambda? Or can itemgetter
not be used in this way?
EDIT. takewhile
is being used for a reason. I understand what it does. This function is going to be used on a sorted list. I appreciate that the tuples are backwards for this, but the code that I have used it correct for what I want and expect.
Your lambda function is actually the composition of two functions: operator.itemgetter(1)
and operator.eq
. Doing this in a purely functional style would require a compose()
function, like this one:
def compose(f, g):
def composed(x):
return f(g(x))
return composed
Using this function, you could do
from operator import itemgetter, eq
from functools import partial
def take_items(a):
return takewhile(compose(partial(eq, 1), itemgetter(1)), a)
I don't think this is a godd idea, though. I would probably go with the straight-forward
def take_items(a):
for x in a:
if x[1] != 1:
break
yield x
I think this requires less thinking on part of the reader of the code.