def remove_all_acs_now(dictionary, delete_ac):
for key in dictionary:
acs = dictionary[key]
for ac in acs:
if ac[0] == delete_ac:
acs.remove(ac)
break
return dictionary
def remove_all_acs(dictionary, delete_ac):
for i in dictionary.values(): # .items() / .values() are the fastest ways for dicts, always!
for q in (i):
if q[0] == delete_ac:
i.remove(q)
break
data=generate(200, 10)
from copy import deepcopy
remove_all_acs(dictionary=deepcopy(data), delete_ac="0_0")
remove_all_acs_now(dictionary=deepcopy(data), delete_ac="0_0")
%timeit deepcopy(data) # needed, because we are modifying the original value
502 ms ± 1.83 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit remove_all_acs(dictionary=deepcopy(data), delete_ac="0_0")
539 ms ± 12.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
539 - 502 = 37 ms
%timeit remove_all_acs_now(dictionary=deepcopy(data), delete_ac="0_0")
559 ms ± 44.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
559 - 502 = 57 ms
Further improvements:
The function doesn t need to return anything, since you are modifying the original dict anyway. You wouldn t even need to pass the dict to the function if it is available in the function s scope (probably a tiny bit faster).
然而,正如我在评论中指出的那样:试图利用热带风暴或Numpy(或两者兼有)进行真正的(10x或更快的)改进。
Edit - Test with cython - 6 times faster
Cython is at least 6 times faster. The less there is to delete, the faster it is. The speed of Cython s loops is insane. If there is no matching value (which means nothing to delete), it is about 50 times faster.
from cythondicttest import deletefomdict
import random
from copy import deepcopy
def generate(size, max_connections):
data = {}
keys = [f"{i}_{j}" for i in range(size) for j in range(size)]
for key in keys:
connections = random.randint(1, min(max_connections, 10))
data[key] = [
(random.choice(keys), random.randint(1, 10)) for _ in range(connections)
]
return data
def remove_all_acs_now(dictionary, delete_ac):
for key in dictionary:
acs = dictionary[key]
for ac in acs:
if ac[0] == delete_ac:
acs.remove(ac)
break
return dictionary
data = generate(500, 100)
# %timeit deepcopy(data)
# 3.16 s ± 27.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# %timeit deletefomdict(dictionary=deepcopy(data), delete_ac="0_0")
# 3.2 s ± 26.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# CYTHON:
# 3200 ms - 3160 ms = 40 ms
# %timeit remove_all_acs_now(dictionary=deepcopy(data), delete_ac="0_0")
# 3.41 s ± 122 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# 3410 ms - 3160 ms = 250 ms
做不到很多工作:
创建PYX文档cythondicttest.pyx,将其与Cython汇编成册,你准备去!
# important: use optimized compiler directives
# https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#compiler-directives
cimport cython
import cython
cpdef int deletefomdict(dict[str,list[tuple[str,int]]] dictionary, str delete_ac):
cdef:
Py_ssize_t loop
for i in dictionary.values():
loop=len(i)
for qq in range(loop):
if i[qq][0] == delete_ac:
del i[qq]
break
return 0
如果你以前从未使用过气旋,你会把这些指令(我的违约环境)作为导向,但你会取得更好的结果,使这里和那里的环境遭到破坏。
optionsdict = {
"Options.docstrings": False,
"Options.embed_pos_in_docstring": False,
"Options.generate_cleanup_code": False,
"Options.clear_to_none": True,
"Options.annotate": True,
"Options.fast_fail": False,
"Options.warning_errors": False,
"Options.error_on_unknown_names": True,
"Options.error_on_uninitialized": True,
"Options.convert_range": True,
"Options.cache_builtins": True,
"Options.gcc_branch_hints": True,
"Options.lookup_module_cpdef": False,
"Options.embed": False,
"Options.cimport_from_pyx": False,
"Options.buffer_max_dims": 8,
"Options.closure_freelist_size": 8,
}
configdict = {
"define_macros": [
("NPY_NO_DEPRECATED_API", 1),
("NPY_1_7_API_VERSION", 1),
("CYTHON_USE_DICT_VERSIONS", 1),
("CYTHON_FAST_GIL", 1),
("CYTHON_USE_PYLIST_INTERNALS", 1),
("CYTHON_USE_UNICODE_INTERNALS", 1),
("CYTHON_ASSUME_SAFE_MACROS", 1),
("CYTHON_USE_TYPE_SLOTS", 1),
("CYTHON_USE_PYTYPE_LOOKUP", 1),
("CYTHON_USE_ASYNC_SLOTS", 1),
("CYTHON_USE_PYLONG_INTERNALS", 1),
("CYTHON_USE_UNICODE_WRITER", 1),
("CYTHON_UNPACK_METHODS", 1),
("CYTHON_USE_EXC_INFO_STACK", 1),
("CYTHON_ATOMICS", 1),
],
"undef_macros": [],
"library_dirs": [],
"libraries": [],
"runtime_library_dirs": [],
"extra_objects": [],
"extra_compile_args": ["/O2", "/Oy"],
"extra_link_args": [],
"export_symbols": [],
"swig_opts": [],
"depends": [],
"language": "c",
"optional": None,
}
compiler_directives = {
"binding": True,
"boundscheck": False,
"wraparound": False,
"initializedcheck": False,
"nonecheck": False,
"overflowcheck": False,
"overflowcheck.fold": True,
"embedsignature": False,
"embedsignature.format": "c", # (c / python / clinic)
"cdivision": True,
"cdivision_warnings": False,
"cpow": True,
"always_allow_keywords": False,
"c_api_binop_methods": False,
"profile": False,
"linetrace": False,
"infer_types": True,
"language_level": 3, # (2/3/3str)
"c_string_type": "bytes", # (bytes / str / unicode)
"c_string_encoding": "default", # (ascii, default, utf-8, etc.)
"type_version_tag": False,
"unraisable_tracebacks": True,
"iterable_coroutine": True,
"annotation_typing": True,
"emit_code_comments": True,
"cpp_locals": False,
"legacy_implicit_noexcept": False,
"optimize.use_switch": True,
"optimize.unpack_method_calls": True,
"warn.undeclared": False, # (default False)
"warn.unreachable": True, # (default True)
"warn.maybe_uninitialized": False, # (default False)
"warn.unused": False, # (default False)
"warn.unused_arg": False, # (default False)
"warn.unused_result": False, # (default False)
"warn.multiple_declarators": True, # (default True)
"show_performance_hints": True, # (default True)
}