6

I'd like to build a dictionary in python in which different keys refer to the same element. I have this dictionary:

persons = {"George":'G.MacDonald', "Luke":'G.MacDonald', "Larry":'G.MacDonald'} 

the key refer all to an identical string but the strings have different memory location inside the program, I'd like to make a dictionary in which all these keys refer to the same element, is that possible?

  • Are you saying whenever you create a string it will use one in memory? – jamylak Apr 21 '13 at 08:50
  • Anyway when you construct the dictionary, they are all the exact same string. What application is this for? – jamylak Apr 21 '13 at 09:00
  • `foo = 'G.MacDonald'; persons = {'George': foo, 'Luke': foo, 'Larry': foo}` – JosefAssad Apr 21 '13 at 09:49
  • Perhaps a multi-key dictionary implementation could solve this: http://stackoverflow.com/questions/11449232/multiple-keys-per-value/16966988#16966988 – formiaczek Jun 26 '13 at 00:39
  • **See also:** https://stackoverflow.com/questions/47524648/get-value-from-dictionary-for-first-key-that-exists – dreftymac Feb 14 '21 at 23:26

2 Answers2

5

You could do something like:

import itertools as it

unique_dict = {}
value_key=lambda x: x[1]
sorted_items = sorted(your_current_dict.items(), key=value_key)
for value, group in it.groupby(sorted_items, key=value_key):
    for key in group:
        unique_dict[key] = value

This transforms your dictionary into a dictionary where equal values of any kind(but comparable) are unique. If your values are not comparable(but are hashable) you could use a temporary dict:

from collections import defaultdict
unique_dict = {}
tmp_dict = defaultdict(list)

for key, value in your_current_dict.items():
    tmp_dict[value].append(key)

for value, keys in tmp_dict.items():
    unique_dict.update(zip(keys, [value] * len(keys)))
Bakuriu
  • 98,325
  • 22
  • 197
  • 231
2

If you happen to be using python 3, sys.intern offers a very elegant solution:

for k in persons:
    persons[k] = sys.intern(persons[k])

In Python 2.7, you can do roughly the same thing with one extra step:

interned = { v:v for v in set(persons.itervalues()) }
for k in persons:
    persons[k] = interned[persons[k]]

In 2.x (< 2.7), you can write interned = dict( (v, v) for … ) instead.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365