Sem*_*nic 26 python list-comprehension
假设我有一个list[str]包含时间戳"HH:mm"格式的对象,例如
timestamps = ["22:58", "03:11", "12:21"]
Run Code Online (Sandbox Code Playgroud)
我想将其转换为list[int]每个时间戳的“自午夜以来的分钟数”值的对象:
converted = [22*60+58, 3*60+11, 12*60+21]
Run Code Online (Sandbox Code Playgroud)
...但我想以风格来完成它并使用单个列表理解来完成它。我天真的构建的(语法不正确的)实现类似于:
def timestamps_to_minutes(timestamps: list[str]) -> list[int]:
return [int(hh) * 60 + int(mm) for ts in timestamps for hh, mm = ts.split(":")]
Run Code Online (Sandbox Code Playgroud)
...但这不起作用,因为这for hh, mm = ts.split(":")不是有效的语法。
写同样的东西的有效方式是什么?
澄清一下:我可以看到一个形式上令人满意的解决方案,其形式为:
def timestamps_to_minutes(timestamps: list[str]) -> list[int]:
return [int(ts.split(":")[0]) * 60 + int(ts.split(":")[1]) for ts in timestamps]
Run Code Online (Sandbox Code Playgroud)
...但是这是非常低效的,我不想将字符串分割两次。
wja*_*rea 33
您可以使用内部生成器表达式来进行分割:
[int(hh)*60 + int(mm) for hh, mm in (ts.split(':') for ts in timestamps)]
Run Code Online (Sandbox Code Playgroud)
虽然就我个人而言,我宁愿使用辅助函数:
def timestamp_to_minutes(timestamp: str) -> int:
hh, mm = timestamp.split(":")
return int(hh)*60 + int(mm)
[timestamp_to_minutes(ts) for ts in timestamps]
# Alternative
list(map(timestamp_to_minutes, timestamps))
Run Code Online (Sandbox Code Playgroud)
And*_*ely 13
如果您不想将字符串拆分两次,可以使用:=赋值运算符:
timestamps = [int((s := t.split(":"))[0]) * 60 + int(s[1]) for t in timestamps]
print(timestamps)
Run Code Online (Sandbox Code Playgroud)
印刷:
[1378, 191, 741]
Run Code Online (Sandbox Code Playgroud)
选择:
[1378, 191, 741]
Run Code Online (Sandbox Code Playgroud)
印刷:
[1378, 191, 741]
Run Code Online (Sandbox Code Playgroud)
小智 13
你最初的伪代码
[int(hh) * 60 + int(mm) for ts in timestamps for hh, mm = ts.split(":")]
Run Code Online (Sandbox Code Playgroud)
与您可以做的非常接近:
[int(hh) * 60 + int(mm) for ts in timestamps for hh, mm in [ts.split(':')]]
Run Code Online (Sandbox Code Playgroud)
在 Python 3.9 中,这样的表达式经过了优化,因此在推导式中创建单元素数组只是为了立即访问其单个元素,就像简单的赋值一样快。
Eri*_*nil 11
如果您使用生成器(而不是列表推导式)进行中间步骤,则整个列表仍将在一次传递中进行转换:
timestamps = ["22:58", "03:11", "12:21"]
#NOTE: Use () for generators, not [].
hh_mms = (timestamp.split(':') for timestamp in timestamps)
converted = [int(hh) * 60 + int(mm) for (hh, mm) in hh_mms]
print(converted)
# [1378, 191, 741]
Run Code Online (Sandbox Code Playgroud)
您可以将推导式拆分为多个步骤,写在多行上,并且不需要定义任何函数。
聚会迟到了..但为什么不使用 datetime / timedelta 来转换你的时间呢?
对于“hh:mm”,这可能有点过分了,但您可以轻松地将其调整为更复杂的时间字符串:
from datetime import datetime as dt
import typing
def timestamps_to_minutes(timestamps: typing.List[str]) -> typing.List[any]:
"""Uses datetime.strptime to parse a datetime string and return
minutes spent in this day."""
return [int(((p := dt.strptime(t,"%H:%M")) - dt(p.year,p.month, p.day)
).total_seconds()//60) for t in timestamps]
timestamps = ["22:58", "03:11", "12:21"]
print(timestamps_to_minutes(timestamps))
Run Code Online (Sandbox Code Playgroud)
输出:
[1378, 191, 741]
Run Code Online (Sandbox Code Playgroud)