Pythoner
Pythoner

Reputation: 5595

Why does max(*list) and max(list) do the same thing in python?

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).

Upvotes: 4

Views: 338

Answers (6)

dawg
dawg

Reputation: 104024

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

Upvotes: 1

U13-Forward
U13-Forward

Reputation: 71610

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
>>> 

Upvotes: 1

Denziloe
Denziloe

Reputation: 8132

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)

Upvotes: 1

WorldSEnder
WorldSEnder

Reputation: 5044

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.

Upvotes: 8

Mad Physicist
Mad Physicist

Reputation: 114440

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.

Upvotes: 4

jadki
jadki

Reputation: 492

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)

Upvotes: 2

Related Questions