Home > Back-end >  How to sort list in a sequence with python?
How to sort list in a sequence with python?

Time:07-27

I have a list of dict like this and here D referes to Day and H refers to Hour. I want to sort the list based on those value. How can I do this ?

First Hour should be sorted and then Days should be sorted.

my_list = [
    {"key1":"123D", "key2":"123D"}, {"key1":"48H", "key2":"48H"},  
    {"key1":None, "key2":"154D"}, {"key1":"122D", "key2":"122D"},
    {"key1":"5D", "key2":"5D"} 
]


sorted_list = sorted(
            my_list,
            key=lambda k: (
                (
                    k["key1"] is None,
                    int(k["key1"][:-1]) if k["key1"] else None,
                ),
                (
                   k["key2"] is None,
                    int(k["key2"][:-1]) if k["key2"] else None,
               ),
            ),
        )

Currently I am getting the result like this:

 [{'key1': '5D', 'key2': '5D'},
 {'key1': '48H', 'key2': '48H'},
 {'key1': '122D', 'key2': '122D'},
 {'key1': '123D', 'key2': '123D'},
 {'key1': None, 'key2': '154D'}]

But what I want is

 [{'key1': '48H', 'key2': '48H'},
 {'key1': '5D', 'key2': '5D'},
 {'key1': '122D', 'key2': '122D'},
 {'key1': '123D', 'key2': '123D'},
 {'key1': None, 'key2': '154D'}]

CodePudding user response:

You need to convert the different representations to a common time unit. Convert the days to hours multiplying by 24:

def key(d):

    k1 = (1, None)
    if d["key1"] is not None:
        v1 = int(d["key1"][:-1]) * (24 if "D" in d["key1"] else 1)
        k1 = (0, v1)

    k2 = (1, None)
    if d["key2"] is not None:
        v2 = int(d["key2"][:-1]) * (24 if "D" in d["key2"] else 1)
        k2 = (0, v2)

    return k1, k2


res = sorted(my_list, key=key)
print(res)

Output

[{'key1': '48H', 'key2': '48H'},
 {'key1': '5D', 'key2': '5D'},
 {'key1': '122D', 'key2': '122D'},
 {'key1': '123D', 'key2': '123D'},
 {'key1': None, 'key2': '154D'}]

CodePudding user response:

my_list = [
    {"key1":"123D", "key2":"123D"}, {"key1":"48H", "key2":"48H"},
    {"key1":None, "key2":"154D"}, {"key1":"122D", "key2":"122D"},
    {"key1":"5D", "key2":"5D"}
]


def t(x):
    key1, key2 = x.get("key1") or float("inf"), x.get("key2") or float("inf")
    if isinstance(key1, str):
        key1 = int(key1[:-1]) * 24 if "D" in key1 else int(key1[:-1])

    if isinstance(key2, str):
        key2 = int(key2[:-1]) * 24 if "D" in key2 else int(key2[:-1])

    return key1, key2


print(sorted(my_list,key=t))

CodePudding user response:

You can simply convert your data into Time deltas.

import pandas as pd

data = [
    {"key1":"123D", "key2":"123D"}, {"key1":"48H", "key2":"48H"},  
    {"key1":None, "key2":"154D"}, {"key1":"122D", "key2":"122D"},
    {"key1":"5D", "key2":"5D"} 
]

df = pd.DataFrame(data)

df['key1_dt'] = df['key1'].apply(lambda row: pd.Timedelta(row))
df['key2_dt'] = df['key2'].apply(lambda row: pd.Timedelta(row))
df = 
   key1  key2  key1_dt  key2_dt
0  123D  123D 123 days 123 days
1   48H   48H   2 days   2 days
2  None  154D      NaT 154 days
3  122D  122D 122 days 122 days
4    5D    5D   5 days   5 days
df.sort_values(by=['key1_dt', 'key2_dt']) =
   key1  key2  key1_dt  key2_dt
1   48H   48H   2 days   2 days
4    5D    5D   5 days   5 days
3  122D  122D 122 days 122 days
0  123D  123D 123 days 123 days
2  None  154D      NaT 154 days

CodePudding user response:

See if this works


a_list = [{'key1': '5D', 'key2': '5D'},
 {'key1': '48H', 'key2': '48H'},
 {'key1': '122D', 'key2': '122D'},
 {'key1': '123D', 'key2': '123D'},
 {'key1': None, 'key2': '154D'}]

def sort_list(a_list):
    keys = [i['key1'] if i['key1'] else i['key2'] for i in a_list]
    # sort the keys 'H' means hours, 'D' means days
    # convert h and d to seconds
    keys_seconds = {}
    for i in keys:
        if i[-1] == 'H':
            keys_seconds[i] = int(i[:-1]) * 3600
        elif i[-1] == 'D':
            keys_seconds[i] = int(i[:-1]) * 86400
        else:
            keys_seconds[i] = int(i)
    
    # sort the keys_seconds
    keys_seconds_sorted = sorted(keys_seconds.items(), key=lambda x: x[1])
    # convert the sorted keys_seconds to a_list
    a_list_sorted = []
    for i in keys_seconds_sorted:
        for j in a_list:
            if i[0] == j['key1'] or i[0] == j['key2']:
                a_list_sorted.append(j)
                break
    return a_list_sorted

print(sort_list(a_list))
# result 
# [{'key1': '48H', 'key2': '48H'}, {'key1': '5D', 'key2': '5D'}, {'key1': '122D', 'key2': '122D'}, {'key1': '123D', 'key2': '123D'}, {'key1': None, 'key2': '154D'}]

CodePudding user response:

Here's another way:

my_list = [
    {"key1": "123D", "key2": "123D"},
    {"key1": "48H", "key2": "48H"},
    {"key1": None, "key2": "154D"},
    {"key1": "122D", "key2": "122D"},
    {"key1": "5D", "key2": "5D"}
]

def func(d):
    def hours(v):
        if v:
            match v[-1]:
                case 'H':
                    return int(v[:-1])
                case 'D':
                    return int(v[:-1]) * 24
        return -1
    return max(map(hours, d.values()))

print(sorted(my_list, key=func))

Output:

[{'key1': '48H', 'key2': '48H'}, {'key1': '5D', 'key2': '5D'}, {'key1': '122D', 'key2': '122D'}, {'key1': '123D', 'key2': '123D'}, {'key1': None, 'key2': '154D'}]
  • Related