Naturally sort a list of alpha-numeric tuples by the tuple's first element in Python

a 夏天 提交于 2019-12-12 12:23:40

问题


A previous stackoverflow question explains how to sort a list of strings alpha-numerically. I would like to sort a list of tuples alphanumerically by the tuple's first element.

Example 1:

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

Example 2:

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

Update: To emphasize the alphanumeric factor, please review example 2.


回答1:


Using the second answer from the other question, generalized to support any method on item as the basis for getting the key:

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))

This is exactly the same as that answer except generalized to use any callable as the operation on item. If you just wanted to do it on a string, you'd use lambda item: item, if you wanted to do it on a list, tuple, dict, or set, you'd use operator.itemgetter(key_or_index_you_want), or if you wanted to do it on a class instance you could use operator.attrgetter('attribute_name_you_want').

It gives

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

for your example #2.




回答2:


Tuples are by default sorted by their elements, starting at the first. So simply do

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)])

The question you liked to talks about natural sorting, which is different from normal (alphanumeric) sorting.

Lets say you want to do natural sort on the first item only:

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]))



回答3:


As others have pointed out, sorted will use the first element of the tuple by default. If you wish to modify this default behavior you can specify a key to be used during the comparisons.

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

Will return the same as:

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

To sort by the second element however try:

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



回答4:


The natsort module does this by default without any extra work

>>> 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)]


来源:https://stackoverflow.com/questions/6849047/naturally-sort-a-list-of-alpha-numeric-tuples-by-the-tuples-first-element-in-py

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!