【发布时间】:2020-02-16 16:12:07
【问题描述】:
我有一个包含用户名的大列表(大约 60,000 个字符串)。每个用户名代表一个提交。有些用户只提交了一次,即他们是“一次性用户”,因此他们的用户名在此列表中只出现一次。其他人已经多次提交(回访用户),因此他们的用户名可以在此列表中多次出现。我想计算有多少这些一次性用户,并据此获得一些统计数据。以下是我目前正在获取的变量:
import time
start_time = time.time()
users = ["UserA", "UserB", "UserC", "UserA", "UserA", "UserA", "UserB", "UserB", "UserD"] # ...just a sample, this goes up to ~60,000 elements
print(f"1: got users list. Time elapsed: {time.time() - start_time}")
one_time_users = [user for user in users if users.count(user) == 1]
print(f"2: got one-time users list. Time elapsed: {time.time() - start_time}")
returning_users = [user for user in users if users.count(user) != 1]
print(f"3: got returning users list. Time elapsed: {time.time() - start_time}")
frequencies = [users.count(user) for user in set(users)]
print(f"4: calculated frequencies list. Time elapsed: {time.time() - start_time}")
sorted_frequencies = sorted(frequencies, reverse=True) # Descending order, largest first
print(f"5: got sorted frequencies list. Time elapsed: {time.time() - start_time}")
top_ten_frequencies_sum = sum(sorted_frequencies[:10])
print(f"6: got top 10 frequencies sum. Time elapsed: {time.time() - start_time}")
top_ten_frequencies_percentage = round(((top_ten_frequencies_sum / len(users)) * 100), 2)
print(f"7: got top 10 frequencies percentage. Time elapsed: {time.time() - start_time}")
average_submissions_per_user = round(len(users) / len(set(users)), 2)
print(f"8: got average submissions per user. Time elapsed: {time.time() - start_time}")
这个操作非常慢。这是我的输出:
1: got users list. Time elapsed: 0.41695237159729004
2: got one-time users list. Time elapsed: 48.26731848716736
3: got returning users list. Time elapsed: 101.88410639762878
4: calculated frequencies list. Time elapsed: 104.39784860610962
5: got sorted frequencies list. Time elapsed: 104.39850783348083
6: got top 10 frequencies sum. Time elapsed: 104.39853930473328
7: got top 10 frequencies percentage. Time elapsed: 104.39856457710266
8: got average submissions per user. Time elapsed: 104.4005241394043
如您所见,列表推导式花费的时间最多。谁能给我解释一下:
- 为什么它的时间复杂度如此之慢。
- collections.Counter() 是否会是更好的选择以及如何最好地在此处应用它。
谢谢!
【问题讨论】:
-
在循环中使用
.count是一种二次时间算法。是的,collections.Counter方法明显更快,它需要线性时间。
标签: python python-3.x list time-complexity list-comprehension