A question was asked here on SO根据值对字典键进行排序。
我刚刚读过关于几天前排序的operator.itemgetter
方法,并决定尝试一下,但它似乎没有用。
并非我对问题的答案有任何问题,我只是想用operator.itemgetter
来尝试。
所以dict是:
>>> mydict = { 'a1': ['g',6],
'a2': ['e',2],
'a3': ['h',3],
'a4': ['s',2],
'a5': ['j',9],
'a6': ['y',7] }
我试过了:
>>> l = sorted(mydict.itervalues(), key=operator.itemgetter(1))
>>> l
[['e', 2], ['s', 2], ['h', 3], ['g', 6], ['y', 7], ['j', 9]]
这就像我想要的那样。但是,由于我没有完整的字典(mydict.itervalues()
),我试过这个:
>>> complete = sorted(mydict.iteritems(), key=operator.itemgetter(2))
这不起作用(正如我所料)。
那么如何使用operator.itemgetter
对dict进行排序并在嵌套键值对上调用itemgetter
。
答案 0 :(得分:30)
In [6]: sorted(mydict.iteritems(), key=lambda (k,v): operator.itemgetter(1)(v))
Out[6]:
[('a2', ['e', 2]),
('a4', ['s', 2]),
('a3', ['h', 3]),
('a1', ['g', 6]),
('a6', ['y', 7]),
('a5', ['j', 9])]
key参数始终是一次从iterable(mydict.iteritems()
)中提供一个项目的函数。在这种情况下,项目可能类似于
('a2',['e',2])
所以我们需要一个可以将('a2',['e',2])
作为输入并返回2的函数。
lambda (k,v): ...
是一个匿名函数,它接受一个参数 - 一个2元组 - 并将其解压缩到k
和v
。因此,当lambda
函数应用于我们的项目时,k
将为'a2'
而v
将为['e',2]
。
lambda (k,v): operator.itemgetter(1)(v)
应用于我们的项目因此返回
operator.itemgetter(1)(['e',2])
,其中“itemgets”['e',2]
中的第二项,即2。
请注意,lambda (k,v): operator.itemgetter(1)(v)
不是用Python编写代码的好方法。正如gnibbler指出的那样,operator.itemgetter(1)
为每个项目重新计算 。那效率很低。使用operator.itemgetter(1)
的目的是创建一个可以多次应用的函数。您不希望每次都重新创建该功能。 lambda (k,v): v[1]
更具可读性,速度更快:
In [15]: %timeit sorted(mydict.iteritems(), key=lambda (k,v): v[1])
100000 loops, best of 3: 7.55 us per loop
In [16]: %timeit sorted(mydict.iteritems(), key=lambda (k,v): operator.itemgetter(1)(v))
100000 loops, best of 3: 11.2 us per loop
答案 1 :(得分:5)
答案是 - 你做不到。 operator.itemgetter(i)
返回一个callable,返回其参数的项i
,即
f = operator.itemgetter(i)
f(d) == d[i]
它永远不会返回像d[i][j]
这样的东西。如果您真的想以纯粹的功能性方式执行此操作,则可以编写自己的compose()
函数:
def compose(f, g):
return lambda *args: f(g(*args))
并使用
sorted(mydict.iteritems(), key=compose(operator.itemgetter(1),
operator.itemgetter(1)))
请注意,我不建议这样做:)
答案 2 :(得分:5)
itemgetter不支持嵌套(尽管attrgetter确实如此)
你需要像这样压扁字典
sorted(([k]+v for k,v in mydict.iteritems()), key=itemgetter(2))
答案 3 :(得分:0)
通常为kv[1][1]
索引会更快:
>>> from timeit import timeit
>>> setup = 'import operator; g = operator.itemgetter(1); '
>>> setup += 'd = {i: list(range(i+2)) for i in range(100)}'
>>> kwargs = {'setup': setup, 'number': 10000}
>>> timeit('sorted(d.items(), key=lambda kv: kv[1][1])', **kwargs)
0.5251589557155967
>>> timeit('sorted(d.items(), key=lambda kv: g(kv[1]))', **kwargs)
0.7175205536186695
>>> timeit('sorted(d.items(), key=lambda kv: g(kv)[1])', **kwargs)
0.7915238151326776
>>> timeit('sorted(d.items(), key=lambda kv: g(g(kv)))', **kwargs)
0.9781978335231543
答案 4 :(得分:0)
解包元组参数的功能在Python 3中已删除:请参见PEP 3113。
因此,接受的答案对运行python 3.x的人不起作用:
等效的解决方案是
sorted(mydict.items(),key=lambda kv:operator.itemgetter(1)(kv[1]) )