Lauren
Lauren

Reputation: 61

Python dictionary with multiple unique values corresponding to a key

I have 2 lists which correspond to what I would like to be my key:value pairs, for example:

list_1 = [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2] #(key)

list_2 = [x,x,x,y,g,r,t,w,r,r,r,t,f,c,d] #(value)

I've (kind of) been able to create a dictionary via: dict = dict(zip(list_1, [list_2]))

However the problem with this is that it is only picking up '1' as a key and also results in duplicate entries within the list of values for the key.

Can anyone suggest a way to create a dictionary so that only the unique values from list_2 are mapped to their corresponding key?

Thanks

EDIT:

output I'm looking for would be one dictionary keyed by 1 and 2 with lists as values containing only the unique values for each i.e.:

dict = {1: [x,y,g,r,t,w], 2: [r,t,f,c,d]}

Upvotes: 1

Views: 1769

Answers (4)

Fuji Komalan
Fuji Komalan

Reputation: 2047

keys = [1,1,1,1,1,1,1,1,1,2,2,2,2,2,2] 

values = ['x','x','x','y','g','r','t','w','r','r','r','t','f','c','d'] 

result = {}

for key,value in  zip(keys,values):

  if key not in result:

    result[key] = []
    if value not in result[key]:
      result[key].append(value)
  else:

    if value not in result[key]:
      result[key].append(value)


print(result)

{1: ['x', 'y', 'g', 'r', 't', 'w'], 2: ['r', 't', 'f', 'c', 'd']}

Note:

zip(keys,values) this will create a iterable of tuples, each tuple consist of one element from the keys and values.

(1,'x')
(1,'x')

Upvotes: 0

ShadowRanger
ShadowRanger

Reputation: 155418

This sort of problem is properly solved with a collections.defaultdict(set); the defaultdict gives you easy auto-vivificaction of sets for each key on demand, and the set uniquifies the values associated with each key:

from collections import defaultdict

mydict = defaultdict(set)
for k, v in zip(list_1, list_2):
    mydict[k].add(v)

You can then convert the result to a plain dict with list values with:

mydict = {k: list(v) for k, v in mydict.items()}

If order of the values must be preserved, on modern Python you can use dicts instead of set (on older Python, you'd use collections.OrderedDict):

mydict = defaultdict(dict)
for k, v in zip(list_1, list_2):
    mydict[k][v] = True  # Dummy value; we're using a dict to get an ordered set of the keys 

with the conversion to plain dict with list values being unchanged

If the input is already sorted, itertools.groupby is theoretically slightly more efficient (it's actual O(n), vs. average case O(n) using dicts), but in practice the defaultdict is typically as faster or faster (the implementation of groupby has some unavoidable inefficiencies). Just for illustration, the groupby solution would be:

from itertools import groupby
from operator import itemgetter

mydict = {k: {v for _, v in grp} for k, grp in groupby(zip(list_1, list_2), key=itemgetter(0))]

# Or preserving order of insertion:
getval = itemgetter(1)  # Construct once to avoid repeated construction
mydict = {k: list(dict.fromkeys(map(getval, grp)))
          for k, grp in groupby(zip(list_1, list_2), key=itemgetter(0))]

Upvotes: 1

Xiidref
Xiidref

Reputation: 1521

Since a dictionary is a set it cant contain twice the same key but it can have the key once then a list of value for that you can use the one-line method

my_dict = {key:[list_2[i] for i in range(len(list_2)) if list_1[i]==key] for key in set(list_1)}

Or a more classic method

my_dict = {}
for key_id in range(len(list_1)):
    if list_1[key_id] not in my_dict:
        my_dict[list_1[key_id]] = []
    my_dict[list_1[key_id]].append(list_2[key_id])

In both case the result is

my_dict = {1: ['x', 'x', 'x', 'y', 'g', 'r', 't', 'w', 'r'], 2: ['r', 'r', 't', 'f', 'c', 'd']}

Upvotes: 1

jtcloud
jtcloud

Reputation: 559

The problem is your key is too unique. there're only two unique keys 1 and 2. So if you're creating dictionaries you can't have {1:x, 1:y} at same time for example, unless you change the key to something new and unique.

I would use a tuple in your purpose:

list(set(tuple(zip(list_1, list_2))))

The set gives you unique mappings which is what dropping the duplicates.

Upvotes: 0

Related Questions