4

See below example:

>>>f = [[1],[2],[3]]
>>>max(f)
Out[21]: [3]
>>>max(*f)
Out[22]: [3]

The unpack operator did not have an effect here, I am trying to unpack a list and get a maximal value of matrix(two dim list).

Pythoner
  • 5,265
  • 5
  • 33
  • 49
  • Suppose you have `[[1, 2, 3], [4, 5, 6], [0, 9, 10]]` What value are you looking for as the max? – dawg Sep 12 '18 at 00:45
  • @dawg, doesn't matter, the question is why are they the same, we can have other means to get whichever element we want. – Pythoner Sep 12 '18 at 14:54

6 Answers6

8

The documentation for max mentions:

builtin max

max(iterable, *[, key, default])

max(arg1, arg2, *args[, key])

...

If one positional argument is provided, it should be an iterable. The largest item in the iterable is returned. If two or more positional arguments are provided, the largest of the positional arguments is returned.

In the first case you have one positional argument, in the second case you have multiple.


To get what you want, which is the maximal entry in a matrix you could try

max(entry for row in matrix for entry in row)

This will pass one argument to the max function which is a generator that iterates over all the entries in the matrix - triggering the first case which finds the maximum of an iterable.

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64
4

You need to chain the lists into a single iterable to get this to work. itertools.chain will let you do this:

from itertools import chain

max(chain(*f))

To unpack the list without itertools or other imports, use a nested comprehension:

max(x for row in f for x in row)

max has two modes. If you pass in a single positional argument, e.g. f, it will be interpreted as an iterable, and the maximum element of the iterable will be returned. If you pass in multiple positionnant arguments, e.g. *f, it will find the maximum of those elements. Since lists are comparable in Python, both versions are indeed equivalent.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
2

You can put the max of each sublist into a list, and then call the max on that.

max(max(i) for i in f)
jadki
  • 482
  • 1
  • 8
  • 15
1

help(max) should be your first port of call.

Help on built-in function max in module builtins:

max(...)
    max(iterable, *[, default=obj, key=func]) -> value
    max(arg1, arg2, *args, *[, key=func]) -> value

    With a single iterable argument, return its biggest item. The
    default keyword-only argument specifies an object to return if
    the provided iterable is empty.
    With two or more arguments, return the largest argument.

max(f) means max with a single argument, [[1],[2],[3]], and the largest element of this is returned.

max(*f) means max with three arguments, [1], [2], [3], and the largest of these is returned.

Clearly these are equivalent in your example.

But in general you should use the former to find the max of an iterable. It's the correct use case. The latter will break for e.g. f = [1].

For your specific problem, you need to flatten the list of lists into a single iterable and pass it to max. Here is a quick way:

max(element for row in f for element in row)

Denziloe
  • 7,473
  • 3
  • 24
  • 34
1

Its because max will have three lists then get's maximum list, so you can do sum, for integer lists:

>>> f=[[1],[2],[3]]
>>> max(sum(f,[]))
3
>>> 

Also since from:

>>> print(max.__doc__)
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value

With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
>>>

As it says "With two or more arguments, return the largest argument.", so we have three arguments, so 3>2 is True, then [3] is largest argument

Or can use, reduce:

>>> from functools import reduce
>>> max(reduce(lambda x,y: x+y,f))
3
>>> 

even tho kind of similar to Mad Physicist's answer, but i use .from_iterable instead of unpacking:

>>> import itertools
>>> max(itertools.chain.from_iterable(f))
3
>>> 
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
1

Given:

mat=[
    [1, 2, 3],
    [4, 5, 6],
    [0, 9, 10]
]

Either max(mat) or max(*mat) will give the same result because the individual sublist are being compared:

>>> max(mat)
[4, 5, 6]
>>> max(*mat)
[4, 5, 6]

In the first case, max(mat), you have a iterable list of lists returning each sublist one at a time. In the second case, max(*mat), the elements (sublists) within that list of lists are unpacked into multiple individual arguments to max.

If you want the sublist that has the max value in it, use max as a key function:

>>> max(mat, key=max)
[0, 9, 10]

If you want the individual max value in a two dimensional matrix, you can flatten it:

>>> max(v for sl in mat for v in sl)
10

Or have three max's:

>>> max(max(mat,key=max))
10
dawg
  • 98,345
  • 23
  • 131
  • 206