【问题标题】:Naturally sort a list of alpha-numeric tuples by the tuple's first element in Python自然地按元组在 Python 中的第一个元素对字母数字元组列表进行排序
【发布时间】:2011-10-14 12:15:48
【问题描述】:

previous stackoverflow question 解释了如何按字母数字对字符串列表进行排序。我想按元组的第一个元素按字母数字对元组列表进行排序。

示例 1:

>>> sort_naturally_tuple([('b', 0), ('0', 1), ('a', 2)])
[('0', 1), ('a', 2), ('b', 0)]

示例 2:

>>> sort_naturally_tuple([('b10', 0), ('0', 1), ('b9', 2)])
[('0', 1), ('b9', 2), ('b10', 0)]

更新:为了强调字母数字因素,请查看示例 2。

【问题讨论】:

  • 它的拼写是sorted(),工作原理完全一样(除了它返回的是生成器而不是列表)。
  • @Kirk sorted 无论输入如何(iter、tuple、genexp)都会返回一个列表...
  • @JBernardo 你是对的,当然。我在想reversed 并在验证之前写了这个。如果我让任何人感到困惑,我深表歉意。

标签: python sorting tuples alphanumeric natural-sort


【解决方案1】:

默认情况下,元组按其元素排序,从第一个开始。所以干脆做

L = [('b', 0), ('0', 1), ('a', 2)]
L.sort()
print L
# or create a new, sorted list
print sorted([('b', 0), ('0', 1), ('a', 2)])

你喜欢谈论自然排序的问题,它不同于普通的(字母数字)排序。

假设您只想对第一项进行自然排序:

import re
def naturalize(item):
    # turn 'b10' into ('b',10) which sorts correctly
    m = re.match(r'(\w+?)(\d+)', item)
    return m.groups()
# now sort by using this function on the first element of the tuple:
print sorted(L, key=lambda tup: naturalize(tup[0]))

【讨论】:

  • 谢谢。抱歉,我没有强调自然排序。 sorted([('b10', 0), ('0', 1), ('b9', 2)]) 返回[('0', 1), ('b10', 0), ('b9', 2)],这是不正确的,因为('b9', 2) 应该在('b10', 0) 之前。
【解决方案2】:

正如其他人指出的那样,默认情况下 sorted 将使用元组的第一个元素。如果您希望修改此默认行为,您可以指定在比较期间使用的键。

sorted([('b', 0), ('0', 1), ('a', 2)])

将返回相同的:

sorted([('b', 0), ('0', 1), ('a', 2)], key=lambda item: item[0])

要按第二个元素排序,但请尝试:

sorted([('b', 0), ('0', 1), ('a', 2)], key=lambda item: item[1])

【讨论】:

  • 对这个方法使用operator.itemgetter,而不是lambda。
  • 不知道这一点。那么类似于 sorted(arr, key=itemgetter(1)(arr)) 的东西按第二个元素排序?谢谢顺便说一句
  • 谢谢。抱歉,我没有强调自然排序。 sorted([('b10', 0), ('0', 1), ('b9', 2)]) 返回 [('0', 1), ('b10', 0), ('b9', 2)],这是不正确的,因为 ('b9', 2) 应该在 ('b10', 0) 之前。
  • from operator import itemgetter; sorted([('b', 0), ('0', 1), ('a', 2)], key=itemgetter(1))
  • sorted([('b10', 0), ('0', 1), ('b9', 2)], key=lambda item: item[0]) 返回[('0', 1), ('b10', 0), ('b9', 2)],这是不正确的,因为('b9', 2) 应该在('b10', 0) 之前。
【解决方案3】:

使用另一个问题的第二个答案,泛化以支持项目上的任何方法作为获取密钥的基础:

import re
from operator import itemgetter

def sorted_nicely(l, key):
    """ Sort the given iterable in the way that humans expect."""
    convert = lambda text: int(text) if text.isdigit() else text
    alphanum_key = lambda item: [ convert(c) for c in re.split('([0-9]+)', key(item)) ]
    return sorted(l, key = alphanum_key)


print sorted_nicely([('b10', 0), ('0', 1), ('b9', 2)], itemgetter(0))

这与该答案完全相同,只是一般化使用 any callable 作为对项目的操作。如果你只是想在一个字符串上做,你会使用lambda item: item,如果你想在一个列表、元组、字典或集合上做,你会使用operator.itemgetter(key_or_index_you_want),或者如果你想做它在一个类实例上,你可以使用operator.attrgetter('attribute_name_you_want')

它给了

[('0', 1), ('b9', 2), ('b10', 0)]

对于您的示例 #2。

【讨论】:

  • 当然,只需将key[0] 更改为key['thekeyyouwanttosortby']
  • 简单!嗯,再进一步怎么样?是否可以发送您想要排序的sorted_nicely() 方法?例如sorted_nicely(l, 'key[0]') 将按l 中的第一个元素排序。另一个例子是sorted_nicely(d, 'key[\'the_key_you_want_to_sort_by\')' 将按元素d['the_key_you_want_to_sort_by'] 对字典d 进行排序。
  • 这是完美的。现在我可以将它用于字典、列表和元组!
【解决方案4】:

natsort 模块默认执行此操作,无需任何额外工作

>>> from natsort import natsorted
>>> natsorted([('b', 0), ('0', 1), ('a', 2)])
[('0', 1), ('a', 2), ('b', 0)]
>>> natsorted([('b10', 0), ('0', 1), ('b9', 2)])
[('0', 1), ('b9', 2), ('b10', 0)]

【讨论】:

    猜你喜欢
    • 2023-03-05
    • 1970-01-01
    • 2021-07-28
    • 2016-03-04
    • 2020-08-02
    • 2012-03-08
    • 2012-03-13
    • 1970-01-01
    相关资源
    最近更新 更多