0

I need a list of max values per key. In the following example:

mydict = {
"day1": [[9],[2],[3]], 
"day2": [[4],[5],[6]],
"day3": [[3],[2],[1]]
}

what I need is something like result=[9,6,3]

I tried:

result = max(map(max, i) for i in worksheet.values())

but it just returns me the first key value. As always, thank you very much in advance.

Victor
  • 133
  • 8

5 Answers5

1

While you could use simple indexing, a solution using the latter will not scale for input with arbitrary depths. Instead, use recursion with max:

flattened = lambda x:[c for h in [[i] if not isinstance(i, list) else flattened(i) for i in x] for c in h]
mydict = {'day2': [[4], [5], [6]], 'day3': [[3], [2], [1]], 'day1': [[9], [2], [3]]}
result = {a:max(flattened(b)) for a, b in mydict.items()}

Output:

{'day2': 6, 'day3': 3, 'day1': 9}

With data n-levels deep:

data = {3:[4, 5, 2, [4, [53, [4, 200]]]], 4:[[[56, 3], [4, [[5]]]]]}
new_result = [max(flattened(i)) for i in data.values()]

Output:

[200, 56]
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • Thank you @Ajax1234 ! Is there any way to get the sorted results? I mean, to get `[9,6,3]` instead of `[6, 3, 9]` (acording to sorted order of keys...). I tried: `[max(flattened(i)) for i in sorted(worksheet.values())]`but didn't seem to work.. – Victor May 01 '18 at 01:17
  • @Victor Dictionaries are unsorted, thus, the order of `dict.values` is not guaranteed. However, you can use `dict.items` and use a dictionary comprehension to better retain the overall structure. Please see my recent edit. – Ajax1234 May 01 '18 at 01:22
  • @Victor From Python 3.7 dictionaries will be guaranteed to [keep insertion order](https://mail.python.org/pipermail/python-dev/2017-December/151283.html). I'm not %100 sure but I think the feature is already there in 3.6 just not officially. – Paul Panzer May 01 '18 at 01:31
1

You could use itertools.chain.from_iterable to get rid of one layer of nesting:

>>> from itertools import chain
>>> 
>>> mydict = {
... "day1": [[9],[2],[3]], 
... "day2": [[4],[5],[6]],
... "day3": [[3],[2],[1]]
... }
>>> 
>>> list(map(max, map(chain.from_iterable, mydict.values())))
[9, 6, 3]
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
0

You could do it with this nested list comprehension:

result = [max([i for sublist in mydict[k] for i in sublist]) for k in mydict]

>>> result
[9, 6, 3]

Explanation:

The inner list comprehension:

[i for sublist in mydict[k] for i in sublist]

Flattens each list (each list of lists in your dictionary values). You then take the max() for each of these, when you iterate through for k in my dict

sacuL
  • 49,704
  • 8
  • 81
  • 106
0

You can create a new dict with the max values for each list of lists and using Alex Martelli's list flattening pattern:

>>> {k:max(e for sl in l for e in sl) for k,l in mydict.items()} 
{'day2': 6, 'day3': 3, 'day1': 9}

Same general technique, you can create a list of max values:

>>> [max(e for sl in l for e in sl) for l in mydict.values()] 
[6, 3, 9]

(Which is of limited value IMHO since Python dicts are unordered in Python prior to 3.6)

Of course, this can be sorted if desired:

>>> sorted([max(e for sl in l for e in sl) for l in mydict.values()], reverse=True) 
[9, 6, 3]

(But then which key has which max? It is unclear from your question if that matters...)

dawg
  • 98,345
  • 23
  • 131
  • 206
  • thank you very much, @dawg ...I wasn't aware about dictionaries aren't sorted, but i will really keep your answer in mind about how to create a new dict with max values only, it would be useful for me in future applications. Once again, thank you very much! – Victor May 01 '18 at 21:43
-1

The issue you're having is that the internal elements are also lists, so you have to unpack them. My first suggestion would be that the structure of mydict is wrong if each of those inner lists is supposed to be only one element long. Possibly it look like this instead:

mydict = {
    "day1": [9, 2, 3], 
    "day2": [4, 5, 6],
    "day3": [3, 2, 1]
}

Alternatively, you'll need to flatten the inner lists. I might do something like:

[max(sum(lists, [])) for lists in mydict.values()]

Note that this version depends on the dictionary being ordered (which is true for the recent enough versions of python, but definitely not all versions.

Julian
  • 2,483
  • 20
  • 20
  • Never ever use [`sum` to concatenate lists](https://stackoverflow.com/a/952952/7207392). – Paul Panzer May 01 '18 at 01:16
  • Thank you very much, Julian! You guys are terrific! Unfortunately I'm afraid I need a list of lists, sometimes a few of them will cointain multiple values, I just used a single value per list to keep it simple on the example. Once again thank you very much for your time and dedication. – Victor May 01 '18 at 01:37