from operator import itemgetter
from itertools import takewhile
xs = [ ('foo',1), ('bar',1), ('baz',2) ]
xs
按第二项排序 - 1
之后不再有'bar'
个。
def item_map(xs):
getcount = itemgetter(1)
return list(map(getcount,xs))
print(item_map(xs))
>>> [1, 1, 2]
返回每个元组的第二个元素的列表。
def item_take(xs):
return list(takewhile(lambda x: x[1] == 1, xs))
print(item_take(xs))
[('foo', 1), ('bar', 1)]
返回具有== 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
不会返回具有== 1
的第二个元素的元组有没有办法用itemgetter
代替lambda?或者itemgetter
不能以这种方式使用?
EDIT。 takewhile
被用于某种原因。我明白它的作用。此函数将用于排序列表。我很欣赏元组是向后的,但是我使用它的代码对我想要和期望的东西是正确的。
答案 0 :(得分:2)
尝试:
getcount = itemgetter(1)
match = lambda x: getcount(x) == 1
你做了什么把itemgetter(1)
简化为1.这个comaprison返回False。然后你打电话给那个。 False(x)
无效,因此您有此错误。
itemgetter(n)
基本上类似于:
def itemgetter(n):
return lambda x: x[n]
您注意到返回另一个函数,将其与int
进行比较是没有意义的。
答案 1 :(得分:2)
你的lambda函数实际上是两个函数的组合:operator.itemgetter(1)
和operator.eq
。以纯函数样式执行此操作需要compose()
函数,如下所示:
def compose(f, g):
def composed(x):
return f(g(x))
return composed
使用此功能,您可以
from operator import itemgetter, eq
from functools import partial
def take_items(a):
return takewhile(compose(partial(eq, 1), itemgetter(1)), a)
但是,我认为这不是一个好主意。我可能会选择直截了当的
def take_items(a):
for x in a:
if x[1] != 1:
break
yield x
我认为这需要对代码的部分读者进行较少的思考。
答案 2 :(得分:1)
itemgetter
不进行比较,它只是为您提供一个检索项目的函数。如果你想进行比较,你需要自己动手。
另请注意,您可以使用列表推导:
def could_this_work(xs):
return [x for x in xs if x[1] == 1]
甚至是生成器表达式,它甚至可以在无限的流上懒惰地工作:
def could_this_work(xs):
return (x for x in xs if x[1] == 1)
(这些做你的英语所说的:在第二个元素中获取1的项目。如果你想在找到非1元素时停止,请使用Sven的答案。)
答案 3 :(得分:0)
请不要在实际代码中执行此操作。老实说,只需使用lambda。
from operator import itemgetter, eq
from functools import partial
from itertools import takewhile
def compose_unary(func1, func2):
return lambda x: func1(func2(x))
def item_take(xs):
return list(takewhile(compose_unary(partial(eq, 1), itemgetter(1)), xs))
请注意,takewhile
实际上并没有像你想象的那么完美;它将停在与谓词不匹配的第一个元素上,并忽略那个超出谓词的任何内容。