pythonlistsortingmixed

sort a list of string and number base on both with specific order


I'm looking for the best practice of sorting my_list like my_ordered_list.

my_list = ['1h-data', '1m-data', '15m-data' , '4h-data', '50s-data']
my_ordered_list = ['50s-data', '1m-data', '15m-data', '1h-data', '4h-data']

I can define my_specific list for string part like: ['s', 'm' , 'h'] and then sort two times first by string part and second by integer part and finally join them, but there must be a better one.


Solution

  • Try this way with index:

    >>> sorted(my_list, key=lambda x: (['s', 'm', 'h'].index(x.split('-')[0][-1]), int(x.split('-')[0][:-1])))
    ['50s-data', '1m-data', '15m-data', '1h-data', '4h-data']
    >>> 
    

    Or with python version >= Python 3.8, you could use the walrus operator:

    >>> sorted(my_list, key=lambda x: (['s', 'm', 'h'].index((t:=x.split('-')[0])[-1]), int(t[:-1])))
    ['50s-data', '1m-data', '15m-data', '1h-data', '4h-data']
    >>> 
    

    Edit:

    If you have stuff like 80s, try:

    my_list = ['1h-data', '1m-data', '15m-data' , '4h-data', '80s-data']
    dct = {"s": 1, "m": 60, "h": 3600}
    def func(x):
        a = x.split('-')[0]
        return int(a[:-1]) * dct.get(a[-1])
    print(sorted(my_list, key=func))
    

    Output:

    ['1m-data', '80s-data', '15m-data', '1h-data', '4h-data']