【问题标题】:Python sorting multiple attributesPython对多个属性进行排序
【发布时间】:2011-05-17 00:23:37
【问题描述】:

我有一本像下面这样的字典。键值对或用户名:名称

d = {"user2":"Tom Cruise", "user1": "Tom Cruise"}

我的问题是我需要按名称对这些进行排序,但是如果多个用户包含与上面相同的名称,则我需要按他们的用户名对它们进行排序。我查找了 sorted 函数,但我不太了解 cmp 参数和 lambda。如果有人可以解释这些并帮助我,那就太好了!谢谢:)

【问题讨论】:

    标签: python sorting dictionary sorted


    【解决方案1】:

    cmp 已过时。 lambda 只是做了一个函数。

    sorted(d.iteritems(), key=operator.itemgetter(1, 0))
    

    【讨论】:

    • 问题是这是我班级作业的一部分,我不允许导入运算符之类的库。它唯一的内置功能。我明白你在说什么,我试着即兴发挥。我用的是“sorted(l, key=lambda l:(l[0], l[1]))”,你觉得这和你说的一样吗?
    • 不完全。 lambda x: (x[1], x[0])
    • 所以这个函数正在对名称进行排序,但如果名称相同,那么它会对用户名进行排序,还是让它们保持相同的位置?因为我需要它,所以如果名称相同,那么它会按用户名排序。非常感谢!
    • 按键对它们进行排序。键是一个元组,元组按元素排序。比较元素 0,但如果它们相同,则比较元素 1,依此类推。
    • 所以假设您在列表 [(3,2), (1,2), (1,1)] 中有元组,并且您想按每个中的第二个值对它们进行排序,如果第二个值相同,然后按第一个排序。我应该期待的答案是[(1,1), (1,2), (3,2)]。这是代码在做什么吗?
    【解决方案2】:

    我将详细说明 Ignacio Vazquez-Abrams 的回答。 cmp 已弃用。不要使用它。请改用key 属性。

    lambda 做一个函数。它是一个表达式,因此可以到达普通 def 语句不能到达的地方,但它的主体仅限于单个表达式。

    my_func = lambda x: x + 1
    

    这定义了一个函数,它接受一个参数 x 并返回 x + 1lambda x, y=1: x + y 定义了一个函数,它接受一个 x 参数、一个默认值为 1 的可选 y 参数并返回 x + y。如您所见,它实际上就像一个def 语句,只是它是一个表达式,并且仅限于一个用于正文的表达式。

    key 属性的用途是 sorted 将为要排序的序列的每个元素调用它,并使用它返回的值进行比较。

    list_ = ['a', 'b', 'c']
    sorted(list_, key=lambda x: 1)
    

    请阅读其余部分以获取假设示例。在写这篇文章之前,我没有仔细研究问题。虽然它仍然具有教育意义,所以我会留下它。 我们真的不能说更多,因为

    1. 您无法对dicts 进行排序。你有dictss 的列表吗?我们可以对其进行排序。
    2. 您尚未显示username 密钥。

    我会假设它类似于

    users = [{'name': 'Tom Cruise', 'username': user234234234, 'reputation': 1},
             {'name': 'Aaron Sterling', 'username': 'aaronasterling', 'reputation': 11725}]
    

    如果你想确认我比汤姆克鲁斯更厉害,你可以这样做:

    sorted(users, key=lambda x: x['reputation'])
    

    这只是传递一个函数,该函数返回列表中每个字典的'reputation' 值。但是lambdas 可能会慢一些。大多数时候operator.itemgetter 是你想要的。

    operator.itemgetter 接受一系列键并返回一个函数,该函数接受一个对象并返回其参数值的元组。

    所以f = operator.itemgetter('name', 'username') 将返回与 lambda d: (d['name'], d['username']) 不同之处在于,原则上它应该运行得更快,而且你不必看丑陋的lambda 表达式。

    所以要按名称和用户名对dicts 列表进行排序,只需这样做

    sorted(list_of_dicts, operator.itemgetter('name', 'username'))
    

    这正是 Ignacio Vazquez-Abrams 所建议的。

    【讨论】:

    • 在我看来,键是用户名,值是真实姓名。
    • @Ignacio - 对。我不知何故错过了您解决方案中的iteritems
    • OP 将 dict 指定为“键值对或用户名:名称”,尽管这可能已被编辑。我一开始错过了。
    • @Josh Smeaton,对。我错过了。我认为or 让我失望了。不过,我将保留它,因为它比 Ignacio 的回答提供了对 lambdaitemgetterkey 的更深入的解释。
    • 当然,我最近才了解 itemgetter 并且不知道它可以进行键查找以及位置查找。 +1
    【解决方案3】:

    你应该知道 dict 不能排序。但是 python 2.7 & 3.1 有这个类 collections.OrderedDict。

    所以,

    >>> from collections import OrderedDict
    >>> d=OrderedDict({'D':'X','B':'Z','C':'X','A':'Y'})
    >>> d
    OrderedDict([('A', 'Y'), ('C', 'X'), ('B', 'Z'), ('D', 'X')])
    >>> OrderedDict(sorted((d.items()), key=lambda t:(t[1],t[0])))
    OrderedDict([('C', 'X'), ('D', 'X'), ('A', 'Y'), ('B', 'Z')])
    

    【讨论】:

    • 是的,实际上它是否是字典无关紧要,我所需要的只是如果我说出了人们的姓名和用户名,我需要对姓名进行排序,但如果两个或更多人有相同的名字,就会出现问题,在这种情况下,我需要按用户名(仅那些人)对这些人进行排序。
    猜你喜欢
    • 1970-01-01
    • 2011-05-13
    • 2012-01-06
    • 2011-05-17
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多