使用operator.itemgetter对字典进行排序

use*_*312 19 python sorting dictionary

几分钟前,在SO上根据它们的值对字典键进行排序时,问了一个问题.

我刚刚读operator.itemgetter了几天前的排序方法,并决定尝试一下,但它似乎没有起作用.

并不是我对问题的答案有任何问题,我只是想尝试一下operator.itemgetter.

所以这个词是:

>>> mydict = { 'a1': ['g',6],
           'a2': ['e',2],
           'a3': ['h',3],
           'a4': ['s',2],
           'a5': ['j',9],
           'a6': ['y',7] }
Run Code Online (Sandbox Code Playgroud)

我试过这个:

>>> l = sorted(mydict.itervalues(), key=operator.itemgetter(1))
>>> l
[['e', 2], ['s', 2], ['h', 3], ['g', 6], ['y', 7], ['j', 9]]
Run Code Online (Sandbox Code Playgroud)

这就像我想要的那样.但是,由于我没有完整的字典(mydict.itervalues()),我试过这个:

>>> complete = sorted(mydict.iteritems(), key=operator.itemgetter(2))
Run Code Online (Sandbox Code Playgroud)

这不起作用(正如我预期的那样).

那么我如何使用嵌套键值对dict进行排序operator.itemgetter和调用itemgetter.

unu*_*tbu 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])]
Run Code Online (Sandbox Code Playgroud)

关键参数始终是一次从iterable(mydict.iteritems())中提供一个项目的函数.在这种情况下,一个项目可能是这样的

('a2',['e',2])
Run Code Online (Sandbox Code Playgroud)

所以我们需要一个可以('a2',['e',2])作为输入并返回2 的函数.

lambda (k,v): ...是一个匿名函数,它接受一个参数 - 一个2元组 - 并将其解压缩到kv.因此,当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
Run Code Online (Sandbox Code Playgroud)

  • 创建一个itemgetter是相对昂贵的.这为dict中的每个键创建一个 (5认同)
  • @AA:`operator.itemgetter(1)(v)`相当于`v [1]`.你可以用`operator.itemgetter(b)(a)`替换任何'a [b]`的出现,但这不是*我*如何理解你的问题:) (3认同)
  • 无论如何,语法无效,因为`lambda`不使用元组。 (2认同)

Sve*_*ach 5

答案是 - 你做不到. operator.itemgetter(i)返回一个返回i其参数项的callable ,即

f = operator.itemgetter(i)
f(d) == d[i]
Run Code Online (Sandbox Code Playgroud)

它永远不会像simething那样回归d[i][j].如果你真的想以纯粹的功能风格来做这件事,你可以编写自己的compose()函数:

def compose(f, g):
    return lambda *args: f(g(*args))
Run Code Online (Sandbox Code Playgroud)

并使用

sorted(mydict.iteritems(), key=compose(operator.itemgetter(1),
                                       operator.itemgetter(1)))
Run Code Online (Sandbox Code Playgroud)

请注意,我不建议这样做:)


Joh*_*ooy 5

itemgetter不支持嵌套(尽管attrgetter确实如此)

你需要像这样压扁字典

sorted(([k]+v for k,v in mydict.iteritems()), key=itemgetter(2))
Run Code Online (Sandbox Code Playgroud)