1

我已经对 datetime.time 列表进行了排序,并希望创建类似的间隔。如果我有

a = [datetime.time(0,0), datetime.time(8,0), datetime.time(13,0), datetime.time(17,0)]

那么结果应该是这样的:

c = [[datetime.time(0,0),datetime.time(8,0)], [datetime.time(8,0),datetime.time(13,0)],
[datetime.time(13,0),datetime.time(17,0)], [datetime.time(17,0),datetime.time(0,0)]]

这可以使用简单的循环来实现,但是否存在更好的解决方案?

使用循环:

>>> a=[datetime.time(0, 0), datetime.time(3, 0), datetime.time(8, 0), datetime.time(11, 0)]
>>> 
>>> r = []
>>> 
>>> for i in range(0,len(a)):
...     if i+1 < len(a):
...         r.append([a[i],a[i+1]])
...     else:
...         r.append([a[i],a[0]])
... 
>>> r
[[datetime.time(0, 0), datetime.time(3, 0)], [datetime.time(3, 0), datetime.time(8, 0)], [datetime.time(8, 0), datetime.time(11, 0)], [datetime.time(11, 0), datetime.time(0, 0)]]
>>> 

如果我想要结果是什么可以改变

[[datetime.time(0, 0), datetime.time(2, 59, 59)], [datetime.time(3, 0), datetime.time(7, 59, 59)], [datetime.time(8, 0), datetime.time(10, 59, 59)], [datetime.time(11, 0), datetime.time(23, 59, 59)]]
4

5 回答 5

8

你可以试试

a = list(zip(a[:-1], a[1:]))
a.append((a[-1], a[0])])

这给了你一个元组列表。如果你想要一个列表列表,只需执行

>>> a = [list(i) for i in zip(a[:-1], a[1:])]
>>> a.append([a[-1], a[0]])

编辑版本采用 1.[a[-1],a[0]]超出列表理解和 2. zip 在 Python 3+ 中不返回列表的事实

另一种可能性是将第一个值附加到列表中:

>>> tmp = a + a[0]
>>> list(zip(tmp[:,-1], tmp[1:]))

可以说它创建了一个临时列表。您可以a.append(a[0])改为执行此操作,但随后您会修改您的初始列表,这可能是一个问题。

于 2012-09-12T12:20:42.683 回答
5

为了创建这样的范围,我可能会尝试使用生成器:

def make_ranges(lst):
    max_idx = len(lst) - 1
    for i,item in enumerate(lst):
        yield [item, lst[i+1 if i != max_idx else 0] ]

您可以使用关键字参数来判断make_ranges是否是周期性的,如果是周期性的,是否在开头或结尾包含环绕。

然后你可以让你的范围:

a = [1,2,3,4,5,6,7,8]
b = list(make_ranges(a))
print(b == [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,1]]) #True
于 2012-09-12T12:55:35.977 回答
3

还有一个选项1作为单线:但使用了一个非常非 Python 的表达式(恕我直言),这样您就不必在单独的步骤中附加最后一对和第一对:

>>> [list(i) for i in zip(a, a[1:]+[a[0]])]
[[datetime.time(0, 0), datetime.time(8, 0)],
 [datetime.time(8, 0), datetime.time(13, 0)],
 [datetime.time(13, 0), datetime.time(17, 0)],
 [datetime.time(17, 0), datetime.time(0, 0)]]

一种受上述 Pierre - GM 解决方案启发的zip方法。

仅供参考,我更喜欢我最初的答案或皮埃尔的答案。


编辑/更新问题的第二部分:也可以在一个表达式中执行 timedeltas(但我认为没有充分的理由为什么不应该将其拆分为不同的语句......):

>>> [[i, (datetime.datetime(101, 1, 1, j.hour, j.minute, j.second) -
...       datetime.timedelta(seconds=1)
...      ).time()
...  ] for i,j in zip(a, a[1:]+[a[0]])
... ]
[[datetime.time(0, 0), datetime.time(7, 59, 59)],
 [datetime.time(8, 0), datetime.time(12, 59, 59)],
 [datetime.time(13, 0), datetime.time(16, 59, 59)],
 [datetime.time(17, 0), datetime.time(23, 59, 59)]]
于 2012-09-12T13:30:14.620 回答
2

如果不是“简单循环”,列表理解怎么样?像:

>>> b = [[a[x], a[x+1]] for x in range(0, len(a)-1)] + [[a[-1], a[0]]]
>>> b
[[datetime.time(0, 0), datetime.time(8, 0)],
 [datetime.time(8, 0), datetime.time(13, 0)],
 [datetime.time(13, 0), datetime.time(17, 0)],
 [datetime.time(17, 0), datetime.time(0, 0)]]
于 2012-09-12T12:24:20.363 回答
0

您可以使用more_itertools库,它是围绕 python 标准库itertools的配方代码。如果要在迭代时处理元素:

import more_itertools as more
rv = [(x, y) for (x, y) in more.pairwise(a)]

或者简单地说:

rv = list(more.pairwise(a))

同样如前所述,是一个答案, zip 也是一个不错的选择:

rv = list(zip(a[:-1], a[1:]))
于 2022-01-11T04:19:46.983 回答