使用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函数可以提供更优雅的解决方案的类似答案。如果我将这些信息存储在磁盘上,那么最好的数据结构和解决方案是什么?
答案 0 :(得分:3)
我对此有几点评论:
&#34;最佳&#34;很暧昧。它可能意味着最小化算法复杂性,最小化运行时间,最小化内存使用,最简单的实现或读取,最少量的代码等。
除非您有数千个条目,否则可能不值得优化您的数据结构或算法。社区公认的最佳做法是剖析和优化整个计划的速度。
一个简单的实现只不过是加入列表并使用内置的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')
注意:
在此示例中,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。这是一种有效且有意义的简单方法。我可以为你提供代码,但这应该足够清楚了。