Python按日期和打印列表名称对多个列表进行排序

时间:2016-08-22 21:27:26

标签: python list sorting

使用Python 3.5.2我有四个日期列表,每个日期都按升序排列,列表的长度不等。通过查找更长的日期列表生成每个日期列表。样本日期值和数据类型如下所示:

In: print (date, type(date))
Out: 725722.0 <class 'numpy.float64'>

我使用相应的循环构建每个日期列表。要查看我转换为字符串的值并打印每个列表。所以我可以将数据类型排序为numpy float64或转换为字符串。每个列表中的实际数据的相关值(基于特定的过滤器设置)如下所示:

a = [12-17-1987, 11-22-1989, 03-05-1990, 11-12-1990]
b = [12-16-1987, 03-02-1990, 11-12-1990]
c = [10-09-1986, 12-16-1987, 03-05-1990, 11-12-1990]
d = [10-16-1985, 08-20-1986, 10-15-1986, 12-16-1987, 03-02-1990]

我需要按照mm-dd-yyyy按升序排列所有四个列表中的日期,打印每个日期,并在每个日期旁边打印相应列表的名称,如下例所示:

# Desired Printout
10-16-1985  d
08-20-1986  d
10-09-1986  c
10-15-1986  d
12-16-1987  b
12-16-1987  c
12-16-1987  d
12-17-1987  a
11-22-1989  a
03-02-1990  b
03-02-1990  d
03-05-1990  a
03-05-1990  c
11-12-1990  a
11-12-1990  b
11-12-1990  c

这将让我直观地确认四组不同数据中的一系列事件。我会尝试创建一个字典并按日期排序以打印到屏幕或磁盘,但我注意到使用map或lambda函数可以提供更优雅的解决方案的类似答案。如果我将这些信息存储在磁盘上,那么最好的数据结构和解决方案是什么?

4 个答案:

答案 0 :(得分:3)

我对此有几点评论:

  1. &#34;最佳&#34;很暧昧。它可能意味着最小化算法复杂性,最小化运行时间,最小化内存使用,最简单的实现或读取,最少量的代码等。

  2. 除非您有数千个条目,否则可能不值得优化您的数据结构或算法。社区公认的最佳做法是剖析和优化整个计划的速度。

  3. 一个简单的实现只不过是加入列表并使用内置的sorted对它们进行排序。例如,以下是您可能考虑进行排序的一些选项:

    import datetime
    
    a = ['7-1-1987', '1-1-1990']
    b = ['7-2-1987', '1-5-1990']
    c = ['7-1-1987', '1-3-1990']
    d = ['1-10-1985', '7-10-1986']
    
    # hold on to list name
    a = [(i, 'a') for i in a]  # [(date, list_name), ...]
    b = [(i, 'b') for i in b]
    c = [(i, 'c') for i in c]
    d = [(i, 'd') for i in d]
    
    dates = a + b + c + d  # combine into one flat list
    for i in dates: print(i)
    

    输出

    ('7-1-1987', 'a')
    ('1-1-1990', 'a')
    ('7-2-1987', 'b')
    ('1-5-1990', 'b')
    ('7-1-1987', 'c')
    ('1-3-1990', 'c')
    ('1-10-1985', 'd')
    ('7-10-1986', 'd')
    

    方法1 - 将每个日期字符串解析为日期时间对象,对其进行排序,并输出日期时间对象列表。

    dates_1 = [(datetime.datetime.strptime(d, '%m-%d-%Y').date(), l) for d, l in dates]
    dates_1.sort()
    for i in dates_1: print(i)
    

    输出

    (datetime.date(1985, 1, 10), 'd')
    (datetime.date(1986, 7, 10), 'd')
    (datetime.date(1987, 7, 1), 'a')
    (datetime.date(1987, 7, 1), 'c')
    (datetime.date(1987, 7, 2), 'b')
    (datetime.date(1990, 1, 1), 'a')
    (datetime.date(1990, 1, 3), 'c')
    (datetime.date(1990, 1, 5), 'b')
    

    方法2 - 使用lambda函数对日期进行排序,该函数可以动态解析它们,并输出一个(新的)字符串列表。

    dates_2 = sorted(dates, key=lambda d: (datetime.datetime.strptime(d[0], '%m-%d-%Y').date(), d[1]))
    for i in dates_2: print(i)
    

    输出

    ('1-10-1985', 'd')
    ('7-10-1986', 'd')
    ('7-1-1987', 'a')
    ('7-1-1987', 'c')
    ('7-2-1987', 'b')
    ('1-1-1990', 'a')
    ('1-3-1990', 'c')
    ('1-5-1990', 'b')
    

    方法3 - 使用heapq.merge更有效地排序。感谢@friendlydog的建议。

    import datetime
    import heapq
    
    a = ['7-1-1987', '1-1-1990']
    b = ['7-2-1987', '1-5-1990']
    c = ['7-1-1987', '1-3-1990']
    d = ['1-10-1985', '7-10-1986']
    
    def strs_to_dates(date_strs, list_name):
        """
        Convert a list of date strings to a generator of (date, str) tuples.
        """
        return ((datetime.datetime.strptime(date, '%m-%d-%Y').date(), list_name) for date in date_strs)
    
    a = strs_to_dates(a, 'a')
    b = strs_to_dates(b, 'b')
    c = strs_to_dates(c, 'c')
    d = strs_to_dates(d, 'd')
    
    dates_3 = heapq.merge(a, b, c, d)
    for i in dates_3: print(i)
    

    输出

    (datetime.date(1985, 1, 10), 'd')
    (datetime.date(1986, 7, 10), 'd')
    (datetime.date(1987, 7, 1), 'a')
    (datetime.date(1987, 7, 1), 'c')
    (datetime.date(1987, 7, 2), 'b')
    (datetime.date(1990, 1, 1), 'a')
    (datetime.date(1990, 1, 3), 'c')
    (datetime.date(1990, 1, 5), 'b')
    

    注意:

    1. 我认为输入字符串的格式是“日 - 月 - 年”。
    2. 我假设当同一日期在多个列表中时,您希望按列表名称按字母顺序排序。
    3. 我将输出列表格式化为读者练习。
    4. 这两个示例都在Python 2/3下工作。
    5. 在此示例中,key参数是lambda。没有它,它将按字母顺序排序字符串。这让我们可以覆盖它并按年份排序&gt;月份&gt;一天。

      更精细的实现可以利用列表预先排序的保证。维基百科有一个merge algorithms列表供您考虑。

答案 1 :(得分:0)

假设您的日期都被格式化为mm-dd-yyyy(与您的示例不同),这应该可以解决问题:

import itertools

lists = dict(a=['7-1-1987', '1-1-1990'],
             b=['7-2-1987', '1-5-1990'],
             c=['7-1-1987', '1-3-1990'],
             d=['1-10-1985', '7-10-1986'])

for d, v in sorted(itertools.chain(*([(e, n) for e in v] for n, v in lists.items()))):
    print d, v

如果日期格式不正确,则必须向sorted函数添加自定义排序键,以将日期解析为可比较的对象。

答案 2 :(得分:-1)

#  Create the list of all dates, combining the four lists you have. Keep
#  the information about which list value comes from
all_dates = [(x, 'a') for x in a] + [(x, 'b') for x in b] + [(x, 'c') for x in c] + [(x, 'd') for x in d]

#  Sort with key a simple date parser. The way it works is:
#     1. It takes a date 11-12-2012 and splits it by '-' so that we get ['11', '12', '2012']
#     2. Reverses the list ([::-1]) so that the year is the most significant (['2012', '12', '11'])
#     3. Applies int to each so that they are compared as numbers ([2012, 12, 11]). Note that Python can automatically compare things like that
all_dates.sort(key = lambda x: list(map(int, x[0].split('-')[::-1])))

#  Print the result
for date in all_dates:
    print ' '.join(date)

答案 3 :(得分:-2)

老实说,你不需要任何花哨的东西。只需对每个列表中的第一项进行一分钟。然后检查min的值是否在任何列表中,然后执行list.pop()和print。这是一种有效且有意义的简单方法。我可以为你提供代码,但这应该足够清楚了。