4 回答

TA貢獻1783條經驗 獲得超4個贊
您可以使用列表理解(實際上,只是一個生成器表達式),但不是您所想的那樣。構建一個AMs 和PMs 的生成器,然后用它來構建一個Counter實例。
from collections import Counter
trip_counts = Counter(("AM" if trip['start'].hour < 12 else "PM")
for trip in onebike_datetimes)
一個獨立的演示:
from collections import Counter
from types import SimpleNamespace
onebike_datetimes = [
{'start': SimpleNamespace(hour=9)},
{'start': SimpleNamespace(hour=3)},
{'start': SimpleNamespace(hour=14)},
{'start': SimpleNamespace(hour=19)},
{'start': SimpleNamespace(hour=7)},
]
trip_counts = Counter(("AM" if trip['start'].hour < 12 else "PM")
for trip in onebike_datetimes)
assert trip_counts["AM"] == 3
assert trip_counts["PM"] == 2

TA貢獻2003條經驗 獲得超2個贊
保留你的 for 循環要清楚得多。
如果你真的想使用列表理解,你可以這樣做:
l = ["AM" if trip["start"].hour < 12 else "PM" for trip in onebike_datetimes]
am_count = l.count("AM")
trip_counts = {"AM": am_count, "PM": len(l) - am_count}
trip_counts(如果你使用這個,你不需要初始化)

TA貢獻1796條經驗 獲得超7個贊
如果這是DataFrame您正在使用的 pandas,為什么不過濾值并立即對它們求和呢?
這樣的事情可能會起作用:
trip_counts['AM'] = len(trip[trip.loc[:, 'hour'] < 12].index)
trip_counts['PM'] = len(trip[trip.loc[:, 'hour'] >= 12].index)
編輯:我只是對這里給出的答案進行了一些基準測試,因為有些人認為列表理解會自動更快。
正如您所看到的,在這種情況下,常規的 for 循環或多或少具有最佳性能,僅Counter與此處其他答案之一中提到的列表推導的使用相匹配。
請注意,我稍微修改了我的 Pandas 實現以匹配我認為您的數據可能的結構(即,不在 DataFrame 中),因此在每次運行時將您的數據轉換為 DataFrame 可能會有更多的開銷。
基準
生成此圖的代碼如下所示:
import pandas as pd
import numpy as np
from collections import Counter
from types import SimpleNamespace
import perfplot
def gen_data(n):
onebike_datetimes = [
{'start': SimpleNamespace(hour=9)},
{'start': SimpleNamespace(hour=3)},
{'start': SimpleNamespace(hour=14)},
{'start': SimpleNamespace(hour=19)},
{'start': SimpleNamespace(hour=7)},
{'start': SimpleNamespace(hour=14)},
{'start': SimpleNamespace(hour=19)},
{'start': SimpleNamespace(hour=2)},
{'start': SimpleNamespace(hour=20)},
{'start': SimpleNamespace(hour=12)},
]*n
return onebike_datetimes
def use_vanilla_for(a):
# onebike_datetimes = gen_data(n)
onebike_datetimes = a
trip_counts = {'AM': 0, 'PM': 0}
for trip in onebike_datetimes:
if trip['start'].hour < 12:
trip_counts["AM"] += 1
else:
trip_counts["PM"] += 1
return 1
# return trip_counts
def use_list_comp(a):
# onebike_datetimes = gen_data(n)
onebike_datetimes = a
trip_counts = {'AM': 0, 'PM': 0}
l = ["AM" if trip["start"].hour < 12 else "PM" for trip in onebike_datetimes]
trip_counts = {i: l.count(i) for i in l}
return 1
# return trip_counts
def use_counter(a):
# onebike_datetimes = gen_data(n)
onebike_datetimes = a
trip_counts = {'AM': 0, 'PM': 0}
trip_counts = Counter(("AM" if trip['start'].hour < 12 else "PM")
for trip in onebike_datetimes)
return 1
# return trip_counts
def use_pandas(a):
# onebike_datetimes = gen_data(n)
onebike_datetimes = a
trip = pd.DataFrame(list(map(lambda a: a['start'].hour, onebike_datetimes)), columns=['hrs'])
trip_counts = {'AM': 0, 'PM': 0}
trip_counts['AM'] = len(trip[trip['hrs'] < 12].index)
trip_counts['PM'] = len(trip[trip['hrs'] >= 12].index)
return 1
# return trip_counts
perfplot.show(
setup=lambda n: gen_data(n),
kernels=[
lambda a: use_vanilla_for(a),
lambda a: use_list_comp(a),
lambda a: use_counter(a),
lambda a: use_pandas(a),
],
labels=["vanilla_for", "list_comp", "counter", "dataframe"],
n_range=[2 ** k for k in range(10)],
xlabel="len(a)",
)

TA貢獻1828條經驗 獲得超3個贊
賦值是語句。語句在列表推導中不可用。使用循環
你真的不應該這樣做,但為了完整起見:
trip_counts = {'AM': 0, 'PM': 0}
[trip_counts.__setitem__('AM', trip_counts['AM']+1) if trip['start']['hour'] <12 else trip_counts.__setitem__('PM', trip_counts['PM']+1) for trip in onebike_datetimes]
print(f"With list comprehension: {trip_counts}")
OUT: With list comprehension: {'AM': 1, 'PM': 2}
添加回答
舉報