使用itemgetter测试相等性

时间:2012-06-22 12:15:14

标签: python python-3.x itertools

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被用于某种原因。我明白它的作用。此函数将用于排序列表。我很欣赏元组是向后的,但是我使用它的代码对我想要和期望的东西是正确的。

4 个答案:

答案 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实际上并没有像你想象的那么完美;它将停在与谓词不匹配的第一个元素上,并忽略那个超出谓词的任何内容。