Reputation: 6152
Is there a simpler way to write this code?
def insert(k, v) # v can either be a single number or a list of numbers, and k may or may not exist in self.dict
if k in self.dict:
if isinstance(v, list):
for e in v:
self.dict[k].add(e)
else:
self.dict[k].add(v)
else:
self.dict[k] = {}
if isinstance(v, list):
for e in v:
self.dict[k].add(e)
else:
self.dict[k].add(v)
Upvotes: 2
Views: 231
Reputation: 5405
Here's an exercise in the problem showing use of exception handling and limited recursion - this may be the most efficient way to do it. Although it 'looks' like the code is larger than other solutions, it compiles down into fewer instructions than the others:
>>> class Foo:
... def __init__(self):
... self.dict = {}
...
... def insert(self, k, v):
... try:
... self.dict[k].extend(v) # <-- majority of accesses
... # only execute this one line.
... except KeyError:
... self.dict[k] = []
... self.insert(k, v)
... except TypeError:
... self.dict[k].extend([v])
...
>>> f = Foo()
>>> f.insert('bob', 1)
>>> f.dict
{'bob': [1]}
>>> f.insert('bob', [3, 4])
>>> f.dict
{'bob': [1, 3, 4]}
I believe this will have the fastest performance assuming most of your data is lists of numbers with only occasional single digits. And that the keys don't vary wildly. The single line self.dict[k].extend(v)
should be executed without exceptions the majority of accesses to the object. It incurs no extra cost checking types and testing conditions. Even if single digits were frequent, branching to add them incurs about the same cost as type checking - except this implementation isn't forced to type check every time something is added.
Upvotes: 0
Reputation: 11929
You could use a defaultdict and simplify the code to
def insert(self, k, v):
if isinstance(v, list):
self.dict[k]+=v
else:
self.dict[k].append(v)
Note that in this case the dictionary would need to be defined as:
self.dict = defaultdict(list)
Or, if you want to associate a set to your keys you could just change it to defaultdict(set)
and use:
def insert(self, k, v):
if isinstance(v, list):
self.dict[k]|=set(v)
else:
self.dict[k].add(v)
Upvotes: 2
Reputation: 73480
Without any changes to the types you use, you can also just do the following in one line:
def insert(k, v):
d.setdefault(k, []).extend(v if isinstance(v, list) else [v])
Or, when using sets:
def insert(k, v):
d.setdefault(k, set()).update(v if isinstance(v, list) else [v])
Upvotes: 0
Reputation: 42492
def insert(k, v):
entries = self.dict.setdefault(k, set())
if isinstance(v, list):
entries.update(v)
else:
entries.add(v)
Upvotes: 0