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'}]