python列表理解与附加步骤(将第一个元素与其自身进行比较,然后首先与第二个元素进行比较,第二个与第三个元素进行比较...)

时间:2020-05-13 09:53:58

标签: python list list-comprehension timedelta

我有一个时间戳,格式为%H:%M:%S。使用以下功能,我可以得到经过的时间:

# time diff func
def time_diff(t1, t2):
return datetime.strptime(t1, '%H:%M:%S') - datetime.strptime(t2, '%H:%M:%S')

# elapsed time since start
data['time'] = [time_diff(data['time'][i], data['time'][0]) for i in range(len(data['time']))]

我还想计算连续数据条目之间的时间增量。因此,第一和第二之间的时间差,第二和第三之间的时间差,依此类推...下面的列表理解可以完成这项工作:

# get timedelta
timedeltas = [data['time'][i] - data['time'][i-1] for i in range(1 ,len(data['time']))]

结果从第一个条目和第二个条目之间的时间间隔开始。但是我希望列表理解首先将第一个条目与自身进行比较,因此我得到00:00:00作为第一个结果,然后开始将元素与连续元素进行比较(第一个与第二个,第二个与第三个..)。有没有人知道如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

一种非常Pythonic的方法是完全避免使用subsripting(切片),而只需使用以下内容:

[0] + [time_diff(t1, t0) for (t1, t0) in zip(data[1:], data[:-1])]
  • 第一个区别是0-您是用这种方式定义的。
  • 对于其余的差异,我们zip有两个子列表-一个从第二个element元素开始,一直到结尾,另一个从第一个元素开始,一直到最后一个。
  • li>
  • 然后,理解对的zip(zip是生成器对象,因此不会生成对的列表),并使用差异构造目标列表的第二个元素到最后一个元素。

您可以通过替换data[:-1]来提高性能和内存消耗。这将防止创建临时列表data[:-1],并且不会更改功能,因为zip仅在两个列表都未耗尽时才运行。但是,该代码有点脏(IMHO),因为您将长度不等的列表发送到zip

您还可以执行以下操作,跳过data[1:]临时列表的创建:

data_i = iter(data)
next(data_i)
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(data_i, data)]

现在您使用的是3行代码,但没有创建任何临时列表,也没有访问列表可以进行随机访问(仅使用顺序访问)。

您可以使用itertools.islice进一步简化操作:

from itertools import islice
diff = [0] + [time_diff(t1, t0) for (t1, t0) in zip(islice(data, 1, None), data)]

答案 1 :(得分:1)

您尝试过

# get timedelta
timedeltas = [data['time'][i] - data['time'][i-1] if i > 0 else data['time'][i]-data['time'][i] for i in range(len(data['time']))]

? 不过这很丑。我认为代码

timedeltas = [data['time'][0]-data['time'][0]] + [data['time'][i] - data['time'][i-1] for i in range(1 ,len(data['time']))]

为此目的更具可读性

答案 2 :(得分:1)

您可以使用pandas整齐地解决此问题:

import pandas as pd

# I suppose your data is a dictionary
data = {'time': ['12:13:11', '12:14:15', '13:20:31']}

df = pd.DataFrame(data=data)
df.time = pd.to_datetime(df.time)
df['timedeltas'] = df.time.diff() # Produces NaT to first index
df.timedeltas.fillna(pd.Timedelta(seconds=0), inplace=True) # Replaces NaT values with 0-second Timedelta

print(df)

>>> 
                 time timedeltas
0 2020-05-13 12:13:11   00:00:00
1 2020-05-13 12:14:15   00:01:04
2 2020-05-13 13:20:31   01:06:16

我希望这会有所帮助!