Python多个日期时间列表的交集

1 投票
4 回答
2613 浏览
提问于 2025-04-18 17:50

我正在尝试找出5个日期时间对象列表的交集。我知道关于列表交集的问题在这里讨论过很多次,但我的代码表现得并不如我所期待的那样(和其他问题中的代码不一样)。

这里是这5个列表的前3个元素,以及每个列表的确切长度。

[datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7), datetime.datetime(2014, 8, 14, 19, 25, 9)] # length 38790
[datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7), datetime.datetime(2014, 8, 14, 19, 25, 9)] # length 38818
[datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7), datetime.datetime(2014, 8, 14, 19, 25, 9)] # length 38959
[datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7), datetime.datetime(2014, 8, 14, 19, 25, 9)] # length 38802
[datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7), datetime.datetime(2014, 8, 14, 19, 25, 9)] # length 40415

我把这些列表放在一个叫做 times 的列表里。我尝试了两种方法来找交集。

方法1:

intersection = times[0] # make intersection the first list
for i in range(len(times)):
    if i == 0:
        continue
    intersection = [val for val in intersection if val in times[i]]

这种方法得到的交集列表长度是 20189,运行时间为104秒。

方法2:

intersection = times[0] # make intersection the first list
for i in range(len(times)):
    if i == 0:
        continue
    intersection = list(set(intersection) & set(times[i]))

这种方法得到的交集列表长度是 20148,运行时间为0.1秒。

我遇到了两个问题。第一个问题是这两种方法得到的交集大小不同,我完全不知道为什么。第二个问题是日期时间对象 datetime.datetime(2014, 8, 14, 19, 25, 6) 明显在所有5个列表中(见上文),但当我 print (datetime.datetime(2014, 8, 14, 19, 25, 6) in intersection) 时却返回了 False。

4 个回答

0

可能会有重复的时间,你可以简单地这样做:

Python3:

import functools
result = functools.reduce(lambda x, y: set(x) & set(y), times)

Python2:

result = reduce(lambda x, y: set(x) & set(y), times)
0
intersection = set(*times[:1]).intersection(*times[1:])

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

0

列表可以包含重复的项目,这可能会导致长度不一致。为了避免这些重复项,你可以把每个包含日期时间的列表转换成一个集合:

map(set, times)

这样你就会得到一个去掉重复时间的集合列表。要找到交集,你可以使用 set.intersection

intersection = set.intersection(*map(set, times))

根据你的例子,交集将是这个集合:

set([datetime.datetime(2014, 8, 14, 19, 25, 9), datetime.datetime(2014, 8, 14, 19, 25, 6), datetime.datetime(2014, 8, 14, 19, 25, 7)])
1

你的第一个列表 times[0] 中有重复的元素,这就是导致不一致的原因。如果你在你的第一个代码片段中使用 intersection = list(set(times[0])),这个问题就会解决。

至于你的第二段代码,如果你在列表和集合之间不做任何更改,代码会运行得更快:

intersection = set(times[0]) # make a set of the first list
for timeset in times[1:]:
    intersection.intersection_update(timeset)

# if necessary make into a list again
intersection = list(intersection)

实际上,因为 intersection 可以接受多个可迭代对象作为单独的参数,所以你可以简单地用下面的代码替换掉你所有的代码:

intersection = set(times[0]).intersection(*times[1:])

关于 in intersection 的问题,实例是一个真正的 datetime.datetime 对象,还是只是看起来像?至少这些时间戳似乎并不是 时区感知 的。

撰写回答