我有一个名为projects
的项目列表,以及与每个项目相关联的名为tasks
的任务列表。有些项目没有任务,有些任务尚未完成。一些项目也有多项任务。我想生成一个列表列表,显示每个项目,最早的任务开始日期和最新的任务结束日期。如果任务尚未完成,则结束日期应为None
。如果项目没有任务,那么开始和结束日期应该None
。
我的代码会产生错误的结果,所以我想知道原因,但也看看是否有人建议采用更有效的方法。
任务格式:
[项目ID,开始日期,结束日期]
我的代码:
import datetime
tasks = [['ID1', datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 2)],
['ID1', datetime.datetime( 2015, 10, 1), None],
['ID2', datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 3)]]
projects = [['ID1'], ['ID2'], ['ID3']]
for key, item in enumerate(projects):
if item[0] not in tasks:
item.append(None)
item.append(None)
else:
start_date = [x[1:-1] for x in tasks if x[0] == item[0]]
item.append(min(start_date))
end_date = [x[-1] for x in tasks if x[0] == item[0]]
if end_date.count(None) <> 0: #checks to see if there is a None value
item.append(None)
else:
item.append(max(end_date))
print projects
我的输出:
[['ID1', None, None], ['ID2', None, None], ['ID3', None, None]]
期望的输出:
[['ID1', datetime.datetime( 2015, 1, 1), None], ['ID2', datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 3)], ['ID3', None, None]]
答案 0 :(得分:3)
你的问题在
行if item[0] not in tasks:
因为这会检查字符串&#39; IDx&#39;是任务列表的成员。但是,任务是一个列表列表 - 因此它不会直接包含字符串&#34;&#34;。
我的建议是将任务更改为字典 - 比如
tasks = {'ID1': [datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 2)],
'ID1': [datetime.datetime( 2015, 10, 1), None],
'ID2': [datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 3)]}
如果您没有数百万个条目,这应该一样快,但检查条目更容易,更直观。
我的想法是你可以检查'ID1' in tasks
,它将返回True
- 因为在字典上进行的检查是在定义dict访问的键上进行的,即ID在上面给出的一个dict的例子中。
完整的解决方案可能如下所示:
import datetime
tasks = {'ID1':[[datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 2)], [datetime.datetime( 2015, 10, 1), None]],
'ID2':[[datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 3)]]
}
projects = [['ID1'], ['ID2'], ['ID3']]
for key, item in enumerate(projects):
if item[0] not in tasks:
item.append(None)
item.append(None)
else:
start_date = [x[0] for x in tasks[item[0]]]
if start_date.count(None) != 0: #checks to see if there is a None value
item.append(None)
else:
item.append(min(start_date))
end_date = [x[1] for x in tasks[item[0]]]
if end_date.count(None) != 0: #checks to see if there is a None value
item.append(None)
else:
item.append(max(end_date))
print projects
输出结果为:
[['ID1', datetime.datetime(2015, 1, 1, 0, 0), None], ['ID2', datetime.datetime(2015, 1, 1, 0, 0), datetime.datetime(2015, 1, 3, 0, 0)], ['ID3', None, None]]
如果你想完全转到字典,即包括项目数据,这就是答案:
import datetime
tasks = {'ID1':[[datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 2)], [datetime.datetime( 2015, 10, 1), None]],
'ID2':[[datetime.datetime( 2015, 1, 1), datetime.datetime( 2015, 1, 3)]]
}
projects = [['ID1'], ['ID2'], ['ID3']]
projects_dict = {}
for key, item in enumerate(projects):
projects_dict[item[0]] = []
if item[0] not in tasks:
projects_dict[item[0]].append(None)
projects_dict[item[0]].append(None)
else:
start_date = [x[0] for x in tasks[item[0]]]
if start_date.count(None) != 0: #checks to see if there is a None value
projects_dict[item[0]].append(None)
else:
projects_dict[item[0]].append(min(start_date))
end_date = [x[1] for x in tasks[item[0]]]
if end_date.count(None) != 0: #checks to see if there is a None value
projects_dict[item[0]].append(None)
else:
projects_dict[item[0]].append(max(end_date))
print projects_dict
哦,而且dict-only方法的结果(我认为这是首选的)是:
{'ID2': [datetime.datetime(2015, 1, 1, 0, 0), datetime.datetime(2015, 1, 3, 0, 0)], 'ID3': [None, None], 'ID1': [datetime.datetime(2015, 1, 1, 0, 0), None]}
编辑:fyi - 在Python中将列表列表转换为dicts的一般方法是(以下不是最简洁的,但它是最容易理解的):
dictionary = {}
for list in list_of_lists:
dictionary[list[0]] = list[1:]
答案 1 :(得分:0)
这里最简单的修正是替换线:
if item[0] not in tasks:
有类似的东西:
if not any((item[0] in x for x in tasks))
使用像@cleros建议的字典是一种更好的方法,如果它适用于其余的代码,特别是如果ID
s更像是键而不仅仅是列表的第一个元素。
另外,我建议的方法效率低下,但这并不重要。如果效率很重要,您还可以创建一个中间列表或设置为使用
从tasks
进行检查
task_keys = [task[0] for task in tasks]
然后:
item[0] not in task_keys
(旁白:else
以下有很多问题,所以如果这条线修好后事情不会立即发挥作用,请不要感到惊讶。)