I need to take an integer n
and add all its digits into a Python dictionary (hashtable) to later access them with an O(1)
complexity.
n = 941726149
d = {}
for i in str(n):
d[i] = None
print(d)
The problem is when there are repeating digits, the dictionary overrides them changing its order. For example, the above code outputs:
{'9': None, '4': None, '1': None, '7': None, '2': None, '6': None}
But the output I need is :
{'9': None, '4': None, '1': None, '7': None, '2': None, '6': None, '1': None, '4': None, '9': None}
I know it's impossible to add repeating keys into a hashtable, so I'm wondering if that data structure can be modified to fit this behavior, or use another (maybe custom)
structure that supports it.
Edit:
Example input and output:
- n = 123455 d[5] = [4, 5]
- n = 987385 d[8] = [1, 4] | d[9] = [0]
Thanks in advance.
CodePudding user response:
Here's an example, that for each digit present in the number, it stores its indexes.
As a note, digits not present in the number won't be present in the structure either, so trying to index them (structure[digit_not_existing_in_number]
) will yield KeyError (that's why dict.get is required). But that can be easily fixed.
code00.py:
#!/usr/bin/env python
import sys
def o1_access_structure(n):
ret = {}
for i, e in enumerate(str(n)):
ret.setdefault(int(e), []).append(i)
return ret
def main(*argv):
ns = (
123455,
987385,
941726149,
)
for n in ns:
print("\n", n)
s = o1_access_structure(n)
for e in range(10):
print(" ", e, s.get(e))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q072713761]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 123455 0 None 1 [0] 2 [1] 3 [2] 4 [3] 5 [4, 5] 6 None 7 None 8 None 9 None 987385 0 None 1 None 2 None 3 [3] 4 None 5 [5] 6 None 7 [2] 8 [1, 4] 9 [0] 941726149 0 None 1 [2, 6] 2 [4] 3 None 4 [1, 7] 5 None 6 [5] 7 [3] 8 None 9 [0, 8] Done.
Or, if you don't care about the digit indexes, but only their presence / frequency, you could use [Python.Docs]: class collections.Counter([iterable-or-mapping]):
>>> from collections import Counter >>> >>> >>> c = Counter(int(e) for e in str(941726149)) >>> >>> for e in range(10): ... print(e, c[e]) ... 0 0 1 2 2 1 3 0 4 2 5 0 6 1 7 1 8 0 9 2
CodePudding user response:
How about creating dict
by default value list
:
def dct_num(n):
dct = {}
str_n = str(n)
for idx,i in enumerate(str_n):
dct.setdefault(int(i), []).append(idx)
return dct
for n in [123455, 941726149, 987385]:
print(dct_num(n))
Output:
{1: [0], 2: [1], 3: [2], 4: [3], 5: [4, 5]}
{9: [0, 8], 4: [1, 7], 1: [2, 6], 7: [3], 2: [4], 6: [5]}
{9: [0], 8: [1, 4], 7: [2], 3: [3], 5: [5]}