Reputation:
The problem that I have is the following: I get from a process, a set of values:
t=903
a=432
c=335
And these values goes in a dictionary, which assign different sequences of t, a and c to different keys
{key1} : (t1 a1 c1, t2 a2 c2, ...tn an cn)
{key2} : (t1 a1 c1, t2 a2 c2, ...tn an cn)
What I would like, is to not add a triplet of values to a key, if the first value (say t), is already present. Basically I would use "t" variable as unique factor for my triplet. This only apply for each key, so I don't mind if I have the same value on key 2...key n; the important is that each key has an unique value of t, and that the 3 values are written in the dictionary only if the value of "t" is unique.
I tried this:
for triplets in dict[key1]:
if not t in triplets:
dict[key1].append(t,a,c)
But this seems to not be working. Am I cycling incorrectly trough the dictionary? Should I use a different structure?
Upvotes: 0
Views: 57
Reputation: 1124548
You can create another level; each value a dictionary keyed on t
:
tripplets = dict.setdefault(key1, {})
if t not in triplets:
triplets[t] = (t, a, c)
This produces:
{
'key1': {'t1': (t1, a1, c2),
't2': (t2, a2, c2)},
...
}
so only add (t?, a?, c?)
if t?
is not already a key in the dict[key1]
dictionary.
You could also replace your triple-value tuples with a custom class that implements __eq__
and __hash__
to be considered equal if their t
value is equal:
class Entry(object):
__slots__ = ('t', 'a', 'c') # save some memory
def __init__(self, t, a, c):
self.t = t
self.a = a
self.c = c
def __eq__(self, other):
if not isinstance(other, Entry): return NotImplemented
return self.t == other.t
def __hash__(self):
return id(self.t)
def __repr__(self):
return '<{0}({1[0]!r}, {1[1]!r}, {1[2]!r})>'.format(type(self).__name__, self)
def __getitem__(self, index):
return getattr(self, 'tac'[index])
then use sets in your dictionary:
dict(key1, set()).add(Entry(t, a, c))
If however, you sometimes wanted to keep t
unique, and a
or c
at other times, there is nothing for it but to do an actual search. Use the any()
function to bail out early if a match has been found:
triplets = dict.setdefault(key1, [])
if not any(triplet[0] == t for triplet in triplets):
# no such t value found
triplets.append((t, a, c))
Upvotes: 2
Reputation: 9105
This sounds a whole lot like... a second dictionary! You could implement your data-structure as follows:
from collections import defaultdict
items = defaultdict(dict)
def add_entry(items, key, t, a, c):
values = items[key]
if t not in values:
values[t] = (a,c)
def get_entry(items, key):
values = items[key]
entry = []
for t, (a,c) in values.iteritems():
entry.extend((t,a,c))
return entry
Usage:
>>> add_entry(items, "test", 1, 2, 3)
>>> get_entry(items, "test")
[1, 2, 3]
>>> add_entry(items, "test", 2, 2, 3)
>>> get_entry(items, "test")
[1, 2, 3, 2, 2, 3]
>>> add_entry(items, "test", 1, 6, 7)
>>> get_entry(items, "test")
[1, 2, 3, 2, 2, 3]
>>> add_entry(items, "test2", 1, 2, 3)
>>> get_entry(items, "test2")
[1, 2, 3]
Replace entry.extend((t,a,c))
with entry.append((t,a,c))
if you want to get back a list of tuples rather than just a list of values.
And of course you could encapsulate this datastructure and the methods that operate on it into a class for better usability if you'd like, like so:
class EntryManager(object):
def __init__(self):
self._items = defaultdict(dict)
def add_entry(self, key, t, a, c):
values = self._items[key]
if t not in values:
values[t] = (a,c)
def get_entry(self, key):
values = self._items[key]
entry = []
for t, (a,c) in values.iteritems():
entry.extend((t,a,c))
return entry
Upvotes: 0