How to use list as key of dictionary?
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Tue Nov 6 05:54:35 EST 2007
On Tue, 06 Nov 2007 10:46:48 +0100, Wildemar Wildenburger wrote:
> Davy wrote:
> > Hi Matimus and Boris,
> >
> > Thank you :)
> >
> > And a further question about vector above rank 1, how can I use it as
> > the key of dictionary?
> >
> > For example, if I have list like L=[[1,2,3],[4,5,6,7]], Then I do
> > L_tuple = tuple(L)
> >>>> L_tuple = ([1,2,3],[4,5,6,7])
> > But {L_tuple:'hello'} cause an error?
> >
> Yes, because your key still contains mutable elements. That should not
> surprise you. If it does, please (re-)read
> <URL:http://docs.python.org/tut/node7.html#SECTION007500000000000000000>
> and <URL:http://docs.python.org/lib/typesmapping.html>.
>
> maybe something like this could help:
>
> def tupleize(non_tuple):
> try:
> return tuple(tupleize(thing) for thing in non_tuple)
> except TypeError:
> # non_tuple is not iterable
> return non_tuple
Not quite, because that will also convert strings to tuples, which may
not be what you want for a general solution.
For the specific example given, a list of lists:
list_of_lists = [[1,2,3], [2,3,4], [5,5,5]]
tuple_of_tuples = tuple([tuple(x) for x in list_of_lists])
The above solution might not scale for deeply nested data structures, or
for arbitrary lists, but it may solve the Original Poster's problem.
An *almost* completely general solution is quite involved (and probably
overkill for most practical uses):
def make_dict_key(K):
try:
hash(K)
return K
except TypeError:
# Not hashable, so can't be used as a dictionary key.
if isinstance(K, dict):
return (type(K),) + tuple(
(key, make_dict_key(value)) for (key, value) in K.iteritems())
else:
try:
return (type(K),) + tuple(make_dict_key(x) for x in K)
except TypeError:
# K is not a sequence-like object.
return (type(K), repr(K))
That works for all data types I've tried, and it insures that the keys it
makes from different types are distinguishable:
e.g.
make_dict_key([(1, 2), (3, 4)]) != make_dict_key({1: 2, 3: 4})
and it is as close to reversible as it is possible to get. However, there
is one limitation that makes it less than completely general: it doesn't
handle cycles. If the prospective key K includes a reference to itself,
Bad Things will happen.
(I leave fixing that limitation as an exercise for the reader.)
--
Steven.
More information about the Python-list
mailing list