根据小时和工作日排序?

时间:2017-03-21 11:02:39

标签: python sorting

我有list这样的dict,我想按如下所示进行排序:

[{'07 PM': [{'Tuesday': 0},
            {'Saturday': 0},
            {'Sunday': 0},
            {'Monday': 0},
            {'Thursday': 0},
            {'Wednesday': 0},
            {'Friday': 0}]},
 {'08 PM': [{'Saturday': 0},
            {'Tuesday': 0},
            {'Monday': 0},
            {'Sunday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Wednesday': 0}]},
 {'05 PM': [{'Saturday': 0},
            {'Sunday': 0},
            {'Monday': 0},
            {'Thursday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Friday': 0}]},
 {'09 PM': [{'Tuesday': 0},
            {'Saturday': 0},
            {'Monday': 0},
            {'Sunday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Wednesday': 0}]},

所需的输出:

[{'01 AM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0},
            ]},
 {'02 AM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0},
            ]},
 {'03 AM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0},
            ]},
]

这就是我希望它按小时(24小时格式)排序,也可以按工作日排序。在这种情况下,以词法方式排序不会有效,所以我尝试将key参数传递给sorted(),其中key按照我想要的正确顺序排列:

sorted(my_unsorted_data, key=sorted_data.index)

其中sorted_data是上面所需的输出,但是出现了这个错误:

{'07 PM': [{'Tuesday': 0}, {'Saturday': 0}, {'Sunday': 0}, {'Monday': 0}, {'Thursday': 0}, {'Wednesday': 0}, {'Friday': 0}]} is not in list

4 个答案:

答案 0 :(得分:1)

按工作日排序

为了使用工作日对您的dicts列表进行排序,您可以定义一个带有工作日作为键和id作为值的dict:

wday_numbers = {
    'Sunday': 0,
    'Monday': 1,
    'Tuesday': 2,
    'Wednesday': 3,
    'Thursday': 4,
    'Friday': 5,
    'Saturday': 6
}


dicts = [{'Tuesday': 0},
         {'Saturday': 0},
         {'Monday': 0},
         {'Sunday': 0},
         {'Thursday': 0},
         {'Friday': 0},
         {'Wednesday': 0}]

print(sorted(dicts, key=lambda x: wday_numbers[list(x.keys())[0]]))
# [{'Sunday': 0}, {'Monday': 0}, {'Tuesday': 0}, {'Wednesday': 0}, {'Thursday': 0}, {'Friday': 0}, {'Saturday': 0}]

排序时间

您可以编写一个帮助函数,将03 AM转换为3,将2 PM转换为14

def to_24h(hour_pm_am):
    hour, pm_am = hour_pm_am.split(' ')
    if pm_am == "PM":
        return int(hour)+12
    else:
        return int(hour)

print(sorted(['07 PM', '08 AM', '03 PM', '03 AM'], key=to_24h))
# ['03 AM', '08 AM', '03 PM', '07 PM']

注意

使用具有单个唯一值的dicts列表通常不是一个好主意。这个dicts列表可以转换为一个dict(如果顺序很重要,可以转换为OrderedDict)。

您将获得完全相同的信息,但检索信息会更容易。

以下是一个例子:

from collections import OrderedDict

wday_numbers = {
    'Sunday': 0,
    'Monday': 1,
    'Tuesday': 2,
    'Wednesday': 3,
    'Thursday': 4,
    'Friday': 5,
    'Saturday': 6
}

dicts = [{'Tuesday': 9},
         {'Saturday': 3},
         {'Monday': 2},
         {'Sunday': 5},
         {'Thursday': 4},
         {'Friday': 7},
         {'Wednesday': 1}]

pairs = [(day, number) for dct in dicts for day, number in dct.items()]
pairs.sort(key=lambda d: wday_numbers[d[0]])
ordered_days = OrderedDict(pairs)

print(ordered_days)
# OrderedDict([('Sunday', 5), ('Monday', 2), ('Tuesday', 9), ('Wednesday', 1), ('Thursday', 4), ('Friday', 7), ('Saturday', 3)])

答案 1 :(得分:1)

列表中的外部字典只有一个密钥,每个密钥的格式为'AM''PM。要对外部词典进行排序,我们可以定义排序键

def sortouter(dic):
    hour_str = dic.keys()[0] # list(dic.keys())[0] in Python 3
    hour, am_pm = hour_str.split()
    return (am_pm, int(hour))

假设您的列表名为dicts,请通过发布

来申请
dicts.sort(key=sortouter)

这将首先按'AM' / 'PM'排序(巧合的是,'AM'按字典顺序排在'PM'之前)和小时秒的数值。

为了对每个内部列表进行排序,循环遍历您的词典列表,并按照它们所拥有的唯一键(工作日)对每个列表进行排序。当然,我们需要另一个排序键来订购工作日。

def sortinner(dic):
    day = dic.keys()[0] # Python 3: list(dic.keys())[0]        
    return {'Sunday': 0, 'Monday': 1, ..., 'Saturday': 7}[day]

循环:

for dic in dicts:
    for lst in dic.values(): # only one iteration with your current format
        lst.sort(key=sortinner)
  

您的解决方案是否有效请您解释一下sortouter如何更详细地工作

当您致电dicts.sort(key=sortouter)时,列表dicts中的词典会传递给sortouter(参数名为dic)。

该函数的第一行只是获取dicts中每个词典中的唯一键,例如'02 AM'

第二行用空格分割字符串,并且 - 坚持示例 - 将'02'分配给名称hour,将'AM'分配给名称am_pm

最后返回的排序键是元组('AM', 2)

现在,Python将对字典列表进行排序,就像它是(AM / PM,整数)元组的列表一样(排序的东西好像看起来像是其他东西背后的整个想法)排序键)。

元组按字典顺序排列,如字符串,即两个元组ts,如果t,则元组s小于t[0] < s[0]。如果t[0] == s[0],则会比较下一个元素t[1]s[1],依此类推。

因此,'AM'&lt; 'PM'(因为'A'&lt;'P')所有'AM' - 在'PM' - dicts之前出现(Python甚至不需要查看返回值sortouter中的整数来做出决定)。在所有'AM' - 或'PM' - dicts的组中,元组sortouter返回的第二个元素被比较(因为第一个元素是相同的),所以字典被排序按升序时间计算。

答案 2 :(得分:0)

这是我的看法。

示例输入数据:

data = [{'07 PM': [{'Tuesday': 0},
                   {'Saturday': 0},
                   {'Sunday': 0},
                   {'Monday': 0},
                   {'Thursday': 0},
                   {'Wednesday': 0},
                   {'Friday': 0}]},
        {'08 AM': [{'Saturday': 0},
                   {'Tuesday': 0},
                   {'Monday': 0},
                   {'Sunday': 0},
                   {'Thursday': 0},
                   {'Friday': 0},
                   {'Wednesday': 0}]},
        {'05 PM': [{'Saturday': 0},
                   {'Sunday': 0},
                   {'Monday': 0},
                   {'Thursday': 0},
                   {'Tuesday': 0},
                   {'Wednesday': 0},
                   {'Friday': 0}]},
        {'09 PM': [{'Tuesday': 0},
                   {'Saturday': 0},
                   {'Monday': 0},
                   {'Sunday': 0},
                   {'Thursday': 0},
                   {'Friday': 0},
                   {'Wednesday': 0}]},
       ]

代码:

WEEKDAY_RANK = dict(zip('Sunday,Monday,Tuesday,Wednesday,'
                        'Thursday,Friday,Saturday'.split(','), range(7)))

def time_to_24(time_of_day):
    hour, am_pm = time_of_day.split()
    return int(hour) + (0 if am_pm == 'AM' else 12)

desired = []
for d in sorted(data, key=lambda d: time_to_24( d.items()[0][0] )):
    time_of_day, values = d.items()[0]
    values.sort(key=lambda d: WEEKDAY_RANK[ d.items()[0][0] ])
    desired.append({time_of_day: values})

from pprint import pprint
pprint(desired)

输出:

[{'08 AM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0}]},
 {'05 PM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0}]},
 {'07 PM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0}]},
 {'09 PM': [{'Sunday': 0},
            {'Monday': 0},
            {'Tuesday': 0},
            {'Wednesday': 0},
            {'Thursday': 0},
            {'Friday': 0},
            {'Saturday': 0}]}]

答案 3 :(得分:0)

更加pythonic的方法

days = {'Sunday':0, 'Monday':1, 'Tuesday':2, 'Wednesday':3, 'Thursday':4, 'Friday':5, 'Saturday':6}

def time_custom(val):
    time = val.keys()[0]
    val[time] = sorted(val[time], key=lambda x: days[x.keys()[0]])
    return time

myList = sorted(myList, key=time_custom )