我开始编写一个代码,可以在游戏板上循环播放maaaaany以解决一些不受关注的问题。
我必须检查其位置取决于其他单元格(B' s)属性的单元格(A' s)。我考虑将它存储在一个集合中,而不是重新猜测这种依赖性。此操作将在两个方向上完成(也可以访问A')。
换句话说,我需要一个能够存储多个2个关系的集合,我关心的是检索对象的性能。我也关心插入和删除的时间,因为我的电路板会随着时间的推移而改变,所以我需要插入新的关系并删除其他关系。
我不确切知道插入/删除与访问之间的比例是什么..
可以使用什么容器? 我不知道内置或任何lib 这样的容器,所以我尝试了以下内容。我希望你能给我一些建议,使用一些天才的lib,或者比我使用的更好的模式。
# -*- coding: utf-8 -*-
from timeit import timeit
from collections import defaultdict
import random
N = 1000
r = range(1,N+1)
numbers = list(r)
divs = list(r)
def build(container_cls):
container = container_cls()
for item in build_set():
container.add(*item)
return container
def build_set():
output = set()
for n in numbers:
for d in divs:
if n % d == 0:
output.add((n,d))
return output
class Container_1:
def __init__(self):
self._a2b = defaultdict(set)
def add(self, a, b):
self._a2b[a].add(b)
def remove(self, a, b):
self._a2b[a].remove(b)
def bs_from_a(self, a):
return self._a2b[a]
def as_from_b(self, b):
return set(a for a,bs in self._a2b.items() if b in bs )
def items(self):
return set((a,b) for a,bs in self._a2b.items() for b in bs)
def __contains__(self, item) :
try :
return item[1] in self._a2b[item[0]]
except IndexError:
return False
class Container_2:
def __init__(self):
self._a2b = defaultdict(set)
self._b2a = defaultdict(set)
def remove(self, a, b):
self._a2b[a].remove(b)
self._b2a[b].remove(a)
def add(self, a, b):
self._a2b[a].add(b)
self._b2a[b].add(a)
def bs_from_a(self, a):
return self._a2b[a]
def as_from_b(self, b):
return self._b2a[b]
def items(self):
return set((a,b) for a,bs in self._a2b.items() for b in bs)
def __contains__(self, item) :
try :
return item[1] in self._a2b[item[0]]
except IndexError:
return False
class Container_3:
def __init__(self):
self._items = set()
def remove(self, a, b):
self._items.remove((a,b))
def add(self, a, b):
self._items.add((a,b))
def bs_from_a(self, a):
return set(bb for aa, bb in self._items if aa == a)
def as_from_b(self, b):
return set(aa for aa, bb in self._items if bb == b)
def items(self):
return set(self._items)
def __contains__(self, item) :
return item in self._items
def time_wrap(command, setup):
N = 10
result = timeit(command, setup, number=N)
print("Setup :", setup)
print("Command :", command)
print("Result :", result)
def time_container(container_cls):
args = {
"cls" : container_cls.__name__,
"N" : N
}
print("\n\n===== {cls} =====".format(**args))
print("---Bulk Add---")
setup = "from __main__ import {cls}, build_set; c={cls}(); items=build_set()".format(**args)
command = "for item in items: c.add(*item)".format(**args)
time_wrap(command,setup)
print("---As from B---")
setup = "from __main__ import {cls}, build; c = build({cls})".format(**args)
command = "for i in range({N}): c.as_from_b(i)".format(**args)
time_wrap(command,setup)
print("---Bs from A---")
setup = "from __main__ import {cls}, build; c = build({cls})".format(**args)
command = "for i in range({N}): c.bs_from_a(i)".format(**args)
time_wrap(command,setup)
print("---Get all items")
setup = "from __main__ import {cls}, build; c = build({cls})".format(**args)
command = "c.items()".format(**args)
time_wrap(command,setup)
print("---Remove all items")
setup = "from __main__ import {cls}, build; c = build({cls})".format(**args)
command = "for item in c.items(): c.remove(*item)".format(**args)
time_wrap(command,setup)
print("---Find if in")
setup = "from __main__ import {cls}, build; from itertools import product; c = build({cls})".format(**args)
command = "for a,b in product(*[range(4)]*2): (a,b) in c".format(**args)
time_wrap(command,setup)
def assert_containers_match(container_cls_1,container_cls_2):
ctn_1 = build(container_cls_1)
ctn_2 = build(container_cls_2)
def assert_match():
assert ctn_1.items() == ctn_2.items()
for i in r:
assert ctn_1.bs_from_a(i) == ctn_2.bs_from_a(i)
assert ctn_1.as_from_b(i) == ctn_2.as_from_b(i)
assert_match()
# Tests for removal
# Only tests 10 samples because it's is too time consuming
for item in random.sample( ctn_1.items(), 10) :
assert item in ctn_1
assert item in ctn_2
ctn_1.remove(*item)
ctn_2.remove(*item)
assert item not in ctn_1
assert item not in ctn_2
assert_match()
assert_containers_match(Container_1, Container_2)
assert_containers_match(Container_1, Container_3)
time_container(Container_1)
time_container(Container_2)
time_container(Container_3)
以下是输出计算时间:
===== Container_1 =====
---Bulk Add---
Setup : from __main__ import Container_1, build_set; c=Container_1(); items=build_set()
Command : for item in items: c.add(*item)
Result : 0.015180546937699546
---As from B---
Setup : from __main__ import Container_1, build; c = build(Container_1)
Command : for i in range(1000): c.as_from_b(i)
Result : 0.3854760317099135
---Bs from A---
Setup : from __main__ import Container_1, build; c = build(Container_1)
Command : for i in range(1000): c.bs_from_a(i)
Result : 0.0014935762328605051
---Get all items
Setup : from __main__ import Container_1, build; c = build(Container_1)
Command : c.items()
Result : 0.008290981613299664
---Remove all items
Setup : from __main__ import Container_1, build; c = build(Container_1)
Command : for item in c.items(): c.remove(*item)
Result : 0.003233156124224479
---Find if in
Setup : from __main__ import Container_1, build; from itertools import product; c = build(Container_1)
Command : for a,b in product(*[range(4)]*2): (a,b) in c
Result : 4.729901911559864e-05
===== Container_2 =====
---Bulk Add---
Setup : from __main__ import Container_2, build_set; c=Container_2(); items=build_set()
Command : for item in items: c.add(*item)
Result : 0.023733136010378075
---As from B---
Setup : from __main__ import Container_2, build; c = build(Container_2)
Command : for i in range(1000): c.as_from_b(i)
Result : 0.0014887000452290522
---Bs from A---
Setup : from __main__ import Container_2, build; c = build(Container_2)
Command : for i in range(1000): c.bs_from_a(i)
Result : 0.0014411572165045072
---Get all items
Setup : from __main__ import Container_2, build; c = build(Container_2)
Command : c.items()
Result : 0.008764215610426618
---Remove all items
Setup : from __main__ import Container_2, build; c = build(Container_2)
Command : for item in c.items(): c.remove(*item)
Result : 0.004034069921999617
---Find if in
Setup : from __main__ import Container_2, build; from itertools import product; c = build(Container_2)
Command : for a,b in product(*[range(4)]*2): (a,b) in c
Result : 4.705520950665232e-05
===== Container_3 =====
---Bulk Add---
Setup : from __main__ import Container_3, build_set; c=Container_3(); items=build_set()
Command : for item in items: c.add(*item)
Result : 0.016531982304513804
---As from B---
Setup : from __main__ import Container_3, build; c = build(Container_3)
Command : for i in range(1000): c.as_from_b(i)
Result : 2.7582481321151135
---Bs from A---
Setup : from __main__ import Container_3, build; c = build(Container_3)
Command : for i in range(1000): c.bs_from_a(i)
Result : 2.835941646664196
---Get all items
Setup : from __main__ import Container_3, build; c = build(Container_3)
Command : c.items()
Result : 0.0014294543666437676
---Remove all items
Setup : from __main__ import Container_3, build; c = build(Container_3)
Command : for item in c.items(): c.remove(*item)
Result : 0.0019024445550712699
---Find if in
Setup : from __main__ import Container_3, build; from itertools import product; c = build(Container_3)
Command : for a,b in product(*[range(4)]*2): (a,b) in c
Result : 4.291044979254366e-05