向集合中添加元素还是将列表 a 转换为集合更好?
Is it better to add elements to a set or to convert list a into a set?
我正在为执行聚合的大数据管道创建逻辑。我需要计算一个字段的唯一值的数量,所以我决定使用 set
's.
考虑到条目的数量可能很大,我不知道哪种计算唯一元素数量的方法会更好。
我想到了两个办法:
1.创建一个空 set
并将每个条目添加到其中。
myset = set()
for entry in entries:
myset.add(entry['key'])
uniques = len(myset)
每次新条目到达时,此选项都必须检查该值是否存在于集合中。如果可能取值的个数少,我觉得可能会更快。
2。创建一个列表,将所有条目附加到它并将其转换为一个集合
mylist = list()
for entry in entries:
mylist.append(entry['key'])
uniques = len(set(mylist))
此选项只会搜索一次唯一值,尽管是在更大的集合中。如果可能值的数量很大(例如:ID 或电子邮件),我认为它可能会更快。
我的假设是否正确?有什么方法可以找到无论条件如何都是最好的唯一值?
让我们创建一个函数来创建我们的条目列表。
def make_entries(size):
return [{'key': random.randint(1, size//2)} for _ in range(size)]
我们将使用它来创建不同大小的列表并测试每种方法的速度。
方法 1:创建一个空集并添加到其中
def add_to_set(entries):
myset = set()
for entry in entries:
myset.add(entry['key'])
return len(myset)
方法二:创建一个列表,然后用它来创建一个集合
def create_from_list(entries):
mylist = list()
for entry in entries:
mylist.append(entry['key'])
return len(set(mylist))
方法 2a:使用列表理解创建列表,然后创建集合
def create_from_list_comprehension(entries):
return len(set([entry['key'] for entry in entries]))
方法 3:使用集合理解 (@schwobaseggl's suggestion in their )
def set_comprehension(entries):
return len({entry['key'] for entry in entries})
接下来,我们可以针对不同的 size
.
值对这些方法中的每一种进行计时
sizes = [10, 50, 100, 500, 1_000, 5_000, 10_000, 50_000, 100_000]
times = []
for size in sizes:
times.append([])
entries = make_entries(size)
nrepeat = 1000
times[-1].append(timeit.timeit('add_to_set(entries)', setup='from __main__ import entries, add_to_set', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('create_from_list(entries)', setup='from __main__ import entries, create_from_list', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('create_from_list_comprehension(entries)', setup='from __main__ import entries, create_from_list_comprehension', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('set_comprehension(entries)', setup='from __main__ import entries, set_comprehension', number=nrepeat) / nrepeat)
我 运行 在我的 Win10 笔记本电脑上使用 Python 3.7.7,其中 print(sys.version)
给出
3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)]
现在,如果我们绘制 times
,我们会发现使用集合理解始终比所有其他方法更快。
在您提出的两种方法之间,直接添加到集合通常比创建列表然后从该列表创建集合更快,但速度并不快:平均快 1.2 倍。
如果您有兴趣,这些是我为 times
获得的数字。列对应不同的方法,行对应不同的大小。
times = [[1.91180001e-06, 2.25380005e-06, 1.43129996e-06, 7.10900058e-07],
[4.31230001e-06, 6.94569992e-06, 3.65169998e-06, 2.49419990e-06],
[1.56470999e-05, 1.50408000e-05, 8.06160003e-06, 5.67660003e-06],
[6.51685999e-05, 7.41121001e-05, 6.79391000e-05, 4.49675000e-05],
[1.40047500e-04, 1.70246000e-04, 9.80658000e-05, 6.99476000e-05],
[8.01188900e-04, 1.00142830e-03, 4.92695100e-04, 5.36500400e-04],
[1.35429690e-03, 1.53512830e-03, 8.99595700e-04, 8.74221300e-04],
[8.91747430e-03, 1.10454779e-02, 8.46084390e-03, 7.77944500e-03],
[1.97166152e-02, 1.95640820e-02, 1.17698472e-02, 1.20813099e-02]]
我正在为执行聚合的大数据管道创建逻辑。我需要计算一个字段的唯一值的数量,所以我决定使用 set
's.
考虑到条目的数量可能很大,我不知道哪种计算唯一元素数量的方法会更好。
我想到了两个办法:
1.创建一个空 set
并将每个条目添加到其中。
myset = set()
for entry in entries:
myset.add(entry['key'])
uniques = len(myset)
每次新条目到达时,此选项都必须检查该值是否存在于集合中。如果可能取值的个数少,我觉得可能会更快。
2。创建一个列表,将所有条目附加到它并将其转换为一个集合
mylist = list()
for entry in entries:
mylist.append(entry['key'])
uniques = len(set(mylist))
此选项只会搜索一次唯一值,尽管是在更大的集合中。如果可能值的数量很大(例如:ID 或电子邮件),我认为它可能会更快。
我的假设是否正确?有什么方法可以找到无论条件如何都是最好的唯一值?
让我们创建一个函数来创建我们的条目列表。
def make_entries(size):
return [{'key': random.randint(1, size//2)} for _ in range(size)]
我们将使用它来创建不同大小的列表并测试每种方法的速度。
方法 1:创建一个空集并添加到其中
def add_to_set(entries):
myset = set()
for entry in entries:
myset.add(entry['key'])
return len(myset)
方法二:创建一个列表,然后用它来创建一个集合
def create_from_list(entries):
mylist = list()
for entry in entries:
mylist.append(entry['key'])
return len(set(mylist))
方法 2a:使用列表理解创建列表,然后创建集合
def create_from_list_comprehension(entries):
return len(set([entry['key'] for entry in entries]))
方法 3:使用集合理解 (@schwobaseggl's suggestion in their
def set_comprehension(entries):
return len({entry['key'] for entry in entries})
接下来,我们可以针对不同的 size
.
sizes = [10, 50, 100, 500, 1_000, 5_000, 10_000, 50_000, 100_000]
times = []
for size in sizes:
times.append([])
entries = make_entries(size)
nrepeat = 1000
times[-1].append(timeit.timeit('add_to_set(entries)', setup='from __main__ import entries, add_to_set', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('create_from_list(entries)', setup='from __main__ import entries, create_from_list', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('create_from_list_comprehension(entries)', setup='from __main__ import entries, create_from_list_comprehension', number=nrepeat) / nrepeat)
times[-1].append(timeit.timeit('set_comprehension(entries)', setup='from __main__ import entries, set_comprehension', number=nrepeat) / nrepeat)
我 运行 在我的 Win10 笔记本电脑上使用 Python 3.7.7,其中 print(sys.version)
给出
3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)]
现在,如果我们绘制 times
,我们会发现使用集合理解始终比所有其他方法更快。
在您提出的两种方法之间,直接添加到集合通常比创建列表然后从该列表创建集合更快,但速度并不快:平均快 1.2 倍。
如果您有兴趣,这些是我为 times
获得的数字。列对应不同的方法,行对应不同的大小。
times = [[1.91180001e-06, 2.25380005e-06, 1.43129996e-06, 7.10900058e-07],
[4.31230001e-06, 6.94569992e-06, 3.65169998e-06, 2.49419990e-06],
[1.56470999e-05, 1.50408000e-05, 8.06160003e-06, 5.67660003e-06],
[6.51685999e-05, 7.41121001e-05, 6.79391000e-05, 4.49675000e-05],
[1.40047500e-04, 1.70246000e-04, 9.80658000e-05, 6.99476000e-05],
[8.01188900e-04, 1.00142830e-03, 4.92695100e-04, 5.36500400e-04],
[1.35429690e-03, 1.53512830e-03, 8.99595700e-04, 8.74221300e-04],
[8.91747430e-03, 1.10454779e-02, 8.46084390e-03, 7.77944500e-03],
[1.97166152e-02, 1.95640820e-02, 1.17698472e-02, 1.20813099e-02]]