简体   繁体   中英

Sort list of string in Python

I need your help to correctly sort the following list of strings.

I have the next list of strings:

listElements = ['2018_1', '2018_10', '2018_2', '2018_3', '2019_1', '2019_10', '2019_2, '2019_3', '2020_1', '2020_10', '2020_2', '2020_3']

And this is the result that I need:

listElements = ['2018_1', '2018_2', '2018_3', '2018_10', '2019_1', '2019_2, '2019_3', '2019_10', '2020_1', 2020_2', '2020_3', 2020_10']

Thanks in advance!

You will have to use sort() with custom compare function. This function compares first part of string (before _ ), then if it is the same, compares second part of string.

def comp(item1, item2):
    i1 = [int(i) for i in item1.split('_')]
    i2 = [int(i) for i in item2.split('_')]
    if i1[0] < i2[0]:
        return -1
    if i1[0] > i2[0]:
        return 1
    if i1[1] < i2[1]:
        return -1
    if i1[1] > i2[1]:
        return 1
    return 0

Here is the driver code:

import functools

listElements = ['2018_1', '2018_10', '2018_2', '2018_3', '2019_1', '2019_10', '2019_2', '2019_3', '2020_1', '2020_10', '2020_2', '2020_3']

def comp(item1, item2):
    i1 = [int(i) for i in item1.split('_')]
    i2 = [int(i) for i in item2.split('_')]
    if i1[0] < i2[0]:
        return -1
    if i1[0] > i2[0]:
        return 1
    if i1[1] < i2[1]:
        return -1
    if i1[1] > i2[1]:
        return 1
    return 0
    
listElements.sort(key=functools.cmp_to_key(comp))
print(listElements)
# ['2018_1', '2018_2', '2018_3', '2018_10', '2019_1', '2019_2, '2019_3', '2019_10', '2020_1', 2020_2, '2020_3', 2020_10']

Solved.

from natsort import natsorted, ns

natsorted(listElements, alg=ns.IGNORECASE)

Using a custom compare function is the “pythonic” way to solve such sorting problems in general.

Another way is to convert the list to a temporary list that can be sorted natively, then convert the result back to the desired format (which need not be the original format).

For example, the following will do what you want:

tmpList = [[int(n) for n in e.split("_")] for e in istElements]
tmpList.sort()
istElements = ["%d_%d" % tuple(p) for p in tmpList]

If you want, you can do all of that within a single statement, using nested list comprehensions or generators, so you don't need the temporary list:

istElements = [
    "%d_%d" % tuple(p)
    for p in sorted(
        [
            int(n)
            for n in e.split("_")
        ]
        for e in istElements
    )
]

I've tried to format the statement across multiple lines so the structure of the list comprehensions becomes clear.

Code

sorted(listElements, key = lambda v: [int(i) for i in v.split('_')])

Result

['2018_1', '2018_2', '2018_3', '2018_10', '2019_1', '2019_2', '2019_3', '2019_10', '2020_1', '2020_2', '2020_3', '2020_10']

Explanation

Key function converts each string to a list of integers which Python list compare function knows how to compare during sorting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM