Python 使用 operator.itemgetter 对字典进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4690416/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sorting dictionary using operator.itemgetter
提问by user225312
A question was asked here on SO, a few minutes ago, on sorting dictionary keys based on their values.
几分钟前,在 SO 上提出了一个问题,即根据字典键的值对其进行排序。
I just read about the operator.itemgettermethod of sorting a few days back and decided to try that, but it doesn't seem to be working.
operator.itemgetter几天前我刚刚阅读了排序方法,并决定尝试一下,但它似乎不起作用。
Not that I have any problems with the answers presented to the questions, I just wanted to try this with operator.itemgetter.
并不是说我对问题的答案有任何问题,我只是想用operator.itemgetter.
So the dict was:
所以字典是:
>>> mydict = { 'a1': ['g',6],
'a2': ['e',2],
'a3': ['h',3],
'a4': ['s',2],
'a5': ['j',9],
'a6': ['y',7] }
I tried this:
我试过这个:
>>> l = sorted(mydict.itervalues(), key=operator.itemgetter(1))
>>> l
[['e', 2], ['s', 2], ['h', 3], ['g', 6], ['y', 7], ['j', 9]]
And this works as I want it to. However, since I don't have the complete dictionary (mydict.itervalues()), I tried this:
这就像我想要的那样工作。但是,由于我没有完整的字典 ( mydict.itervalues()),我尝试了以下操作:
>>> complete = sorted(mydict.iteritems(), key=operator.itemgetter(2))
This doesn't work (as I expected it to).
这不起作用(正如我预期的那样)。
So how do I sort the dict using operator.itemgetterand call itemgetteron the nested key - value pair.
那么我如何使用operator.itemgetter和调用itemgetter嵌套的键值对对dict 进行排序。
采纳答案by unutbu
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])]
The key parameter is always a function that is fed one item from the iterable (mydict.iteritems()) at a time. In this case, an item could be something like
关键参数始终是一个函数,它一次从 iterable ( mydict.iteritems()) 中获取一项。在这种情况下,一个项目可能是这样的
('a2',['e',2])
So we need a function that can take ('a2',['e',2])as input and return 2.
所以我们需要一个可以('a2',['e',2])作为输入并返回 2的函数。
lambda (k,v): ...is an anonymous function which takes one argument -- a 2-tuple -- and unpacks it into kand v. So when the lambdafunction is applied to our item, kwould be 'a2'and vwould be ['e',2].
lambda (k,v): ...是一个匿名函数,它接受一个参数——一个 2 元组——并将其解包到kand 中v。因此,当该lambda函数应用于我们的项目时,k将是'a2'和v将是['e',2]。
lambda (k,v): operator.itemgetter(1)(v)applied to our item thus returns
operator.itemgetter(1)(['e',2]), which "itemgets" the second item in ['e',2], which is 2.
lambda (k,v): operator.itemgetter(1)(v)因此应用于我们的项目返回
operator.itemgetter(1)(['e',2]),它“itemgets” 中的第二个项目['e',2],即 2。
Note that lambda (k,v): operator.itemgetter(1)(v)is not a good way to code in Python. As gnibbler points out, operator.itemgetter(1)is recomputed for each item. That's inefficient. The point of using operator.itemgetter(1)is to create a function that can be applied many times. You don't want to re-create the function each time. lambda (k,v): v[1]is more readable, and faster:
请注意,这lambda (k,v): operator.itemgetter(1)(v)不是在 Python 中编码的好方法。正如 gnibbler 指出的那样,为每个 itemoperator.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
回答by Sven Marnach
The answer is -- you can't. operator.itemgetter(i)returns a callable that returns the item iof its argument, that is
答案是——你不能。 operator.itemgetter(i)返回一个返回i其参数项的可调用对象,即
f = operator.itemgetter(i)
f(d) == d[i]
it will never return simething like d[i][j]. If you really want to do this in a purely functional style, you can write your own compose()function:
它永远不会像d[i][j]. 如果你真的想以纯函数式的方式做到这一点,你可以编写自己的compose()函数:
def compose(f, g):
return lambda *args: f(g(*args))
and use
并使用
sorted(mydict.iteritems(), key=compose(operator.itemgetter(1),
operator.itemgetter(1)))
Note that I did not recommend to do this :)
请注意,我不建议这样做:)
回答by John La Rooy
itemgetter doesn't support nesting ( although attrgetter does)
itemgetter 不支持嵌套(尽管 attrgetter 支持)
you'd need to flatten the dict like this
你需要像这样压平字典
sorted(([k]+v for k,v in mydict.iteritems()), key=itemgetter(2))
回答by Mateen Ulhaq
Indexing normally a la kv[1][1]is faster:
索引通常 a lakv[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

