Here is my solution now, using only one dict.
class StringTable(object):
def __init__(self):
self.table = {}
def probe_id(self, ss):
table = self.table
id_ = hash(ss)
while True:
s = table.get(id_, None)
# id_ not use, return it
if s is None:
return id_, False
# id_ used and equal to ss
if ss == s:
return id_, True
# id_ used by other string, probe again!
id_ = id_ + 1
# don't use this, endless loop, why?
#id_ = hash(id_)
def store(self, ss):
id_, occupied = self.probe_id(ss)
if not occupied:
self.table[id_] = ss
print 'store {%s: %r}' % (id_, ss)
return id_
def get_string_from_id(self, id_):
ret = self.table.get(id_, None)
print 'get_string_from_id %s -> %r' % (id_, ret)
return ret
def get_id_from_string(self, ss):
id_, occupied = self.probe_id(ss)
ret = id_ if occupied else None
print 'get_id_from_string %r -> %s' % (ss, ret)
return ret
st = StringTable()
# http://bugs.python.org/issue14621
s1 = "\x00\xcf\x0b\x96\x19"
s2 = "\x00\x6d\x29\x45\x18"
print repr(s1), hash(s1)
print repr(s2), hash(s2)
id1 = st.store(s1)
id2 = st.store(s2)
st.get_string_from_id(id1)
st.get_string_from_id(id2)
st.get_id_from_string(s1)
st.get_id_from_string(s2)
Output:
jayven@laptop:~/test$ python stringtable.py
'\x00\xcf\x0b\x96\x19' 1220138288
'\x00m)E\x18' 1220138288
store {1220138288: '\x00\xcf\x0b\x96\x19'}
store {1220138289: '\x00m)E\x18'}
get_string_from_id 1220138288 -> '\x00\xcf\x0b\x96\x19'
get_string_from_id 1220138289 -> '\x00m)E\x18'
get_id_from_string '\x00\xcf\x0b\x96\x19' -> 1220138288
get_id_from_string '\x00m)E\x18' -> 1220138289