4

I have a dictionary having following structure

{key1: [1,2,3,4,5], key2: [2,0,4,5,6]}

I need to find maximum and minimum value of each index of the value list, so at index 0, we compare 1 and 2 and choose 2 as the maximum, and 1 as the minimum, etc.

Expected output for my example:

min = [1,0,3,4,5]
max = [2,2,4,5,6]

I cannot use operator as I am not allowed to import it. I tried to used following approach but failed (syntax error). Also I won't iterate through the value set as is not the elegant way (IMO).

maxVal = max(myDictionary.items(), key=(lambda k: myDictionary[k]))

gives me

TypeError: unhashable type: 'list'

Can you correct it or suggest any alternative approach.

user3483203
  • 50,081
  • 9
  • 65
  • 94
Malintha
  • 4,512
  • 9
  • 48
  • 82

1 Answers1

5

You may use zip with min and max:

dct = {'key1': [1,2,3,4,5], 'key2': [2,0,4,5,6]}

[min(i) for i in zip(*dct.values())]
[max(i) for i in zip(*dct.values())]

Output:

[1, 0, 3, 4, 5]
[2, 2, 4, 5, 6]

If you want to get really fancy, you can also use the transpose trick of zip twice to turn this into a one-liner:

min_list, max_list = map(list, zip(*[(min(i), max(i)) for i in zip(*dct.values())]))

min_list
[1, 0, 3, 4, 5]

max_list
[2, 2, 4, 5, 6]

This fancy method behaves badly with empty lists

For example:

dct = {1: [], 2: []}

Will break this method. In fact, pretty much all the ways to break this method involve using an empty list somewhere.


I've mentioned the zip transpose trick twice, so here is why it is necessary here:

If you simply use list(zip(dct.values())), you will get the following output:

[([2, 0, 4, 5, 6],), ([1, 2, 3, 4, 5],)]

This is not the desired result, we want a pairwise comparison of every element at each index of our sublists. However we can leverage the fact that zip is its own tranpose when you use the * operator.

So using list(zip(*dct.values())) provides us with our desired pairwise grouping for comparison:

[(2, 1), (0, 2), (4, 3), (5, 4), (6, 5)]
user3483203
  • 50,081
  • 9
  • 65
  • 94
  • 1
    Wow, thank you for one of the most elegant answers ever got. Can you post a small explanation for the community? – Malintha Jun 13 '18 at 16:45
  • 1
    @Malintha I updated my answer to explain better hopefully. I link near the bottom to a canonical answer that explains this trick very well also. – user3483203 Jun 13 '18 at 16:53