Question: I have a data structure as follows, data = { '0_0': [('0_0', 0), ('0_1', 1), ('0_2', 2)], '0_1': [('0_0', 1), ('0_1', 0), ('0_2', 1)], '0_2': [('0_0', 2), ('0_1', 1), ('0_2', 0)], }  Each key of the dictionary is unique. The values corresponding to the key value in the dictionary structure are list of tuples, and each tuple contains the coordinate name and the distance to that coordinate. How to delete tuple from lists by given key? For example I wrote a function as follows, def remove_all_acs( 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  It's my expected output and returns a result as follows, print(remove_all_acs(data, '0_0')) { '0_0': [('0_1', 1), ('0_2', 2)], '0_1': [('0_1', 0), ('0_2', 1)], '0_2': [('0_1', 1), ('0_2', 0)] }  It works but is not effective on large lists. Do you have any idea? Thanks in advance. In addition you can create large dataset using this code, import math def generate(width, height): coordinates = [(x, y) for x in range(width) for y in range(height)] dataset = {} for x1, y1 in coordinates: key = f"{x1}_{y1}" distances = [] for x2, y2 in coordinates: if (x1, y1) != (x2, y2): distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) distances.append((f"{x2}_{y2}", distance)) dataset[key] = distances return dataset 

Answer: 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). However, like I stated in my comments: try to use Cython or Numpy (or both) for real (10x or faster) improvements. 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  And it is not much work to do: Create a PYX file cythondicttest.pyx, compile it with Cython, and you are ready to go! # 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  If you have never used Cython before, you might use these directives (my default settings) as an orientation, but you might get even better results tweaking the settings here and there. 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) }