Reputation: 349
I'm working with a dictionary, and I'm having a problem, so let's say I have two lists that I need to create a dict, I know, I can use zip to do this, but the thing is, the list I'm using for keys
( list1
) have similar tuples. This is just an example, the lists can have more elements, but the len
in both lists are always the same.
list1 = [(3, 2), (2, 4), (2, 4), (4, 3), (4, 2), (4, 3)]
list2 = [68, 34, 29, 29, 3, 59]
mydict = dict(zip(list1, list2))
print(mydict)
Output:
{(3, 2): 68, (2, 4): 29, (4, 3): 59, (4, 2): 3}
I know that the keys are unique, and if two keys are the same, the associated value will be the last one to appear, but what I need it's that if two keys are the same, then, the associated value needs to be the minimum. For example, in list1
I have two tuples repeated (2,4)
with associated values of 34 and 29, so when the dictionary is created I need to keep the 29, and the other duplicated tuple is (4,3)
with values of 29 and 59, and if the dictionary is created I want the value to be 29, not 59.
my desired output:
{(3, 2): 68, (2, 4): 29, (4, 3): 29, (4, 2): 3}
There is some way I can achieve this? Any help will be appreciated, thank you!
Upvotes: 3
Views: 216
Reputation: 1275
Rather than trying to do a complicated, convoluted one liner or comprehension, a simple for loop will perform fine and maintain readability. My suggestion would be something like this
def merge_lists(list1, list2):
mydict = {}
for k, v in zip(list1,list2):
if (k not in mydict) or (mydict[k] > v):
mydict[k] = v
return mydict
list1 = [(3, 2), (2, 4), (2, 4), (4, 3), (4, 2), (4, 3)]
list2 = [68, 34, 29, 29, 3, 59]
mydict = merge_lists(list1, list2)
print(mydict)
# mydict = {(3, 2): 68, (2, 4): 29, (4, 3): 29, (4, 2): 3}
If you want to play with it more, some further ideas would be to sort list 2 and move the indices of list1 in tandem. Then, with that structure, if you get a repeated element in list1 you know it must it must have come second. You wouldn't really get any perfomance boost or other benefit, but it is an alternative.
Upvotes: 2
Reputation: 5116
from operator import itergetter
from itertools import groupby
pairs = sorted(zip(list1, list2))
minima = {
key: min(value for _, value in group)
for key, group in groupby(sorted(pairs), itemgetter(0))
}
Upvotes: 1
Reputation: 61617
Starting with
keys = [(3, 2), (2, 4), (2, 4), (4, 3), (4, 2), (4, 3)]
values = [68, 34, 29, 29, 3, 59]
Make key-value pairs that are sorted by value, descending, then build the dict from that:
>>> dict(sorted(zip(keys, values), key=lambda x: -x[1]))
{(3, 2): 68, (4, 3): 29, (2, 4): 29, (4, 2): 3}
It's the same idea as your existing dict(zip())
combination but re-ordering the values before building the dictionary, such that entries with lower values appear later - therefore, the minimum value for the key is last to appear.
Upvotes: 4
Reputation: 21453
one way is to sort the entries so that minimum value is last in the list:
def get_value(pair): return pair[1]
list1 = [(3, 2), (2, 4), (2, 4), (4, 3), (4, 2), (4, 3)]
list2 = [68, 34, 29, 29, 3, 59]
mydict = dict(sorted(zip(list1, list2), key=get_value, reverse=True))
Upvotes: 3
Reputation: 1691
One solution is to fill mydict
step-by-step:
list1 = [(3, 2), (2, 4), (2, 4), (4, 3), (4, 2), (4, 3)]
list2 = [68, 34, 29, 29, 3, 59]
mydict = {}
for k,v in zip(list1,list2):
if k in mydict:
mydict[k] = min(mydict[k],v)
else:
mydict[k] = v
print(mydict)
There must be IMO a one-liner solution if desired :-)
Upvotes: 2