Находит максимальное значение элемента в последовательности.
Синтаксис:
max(iterable, *[, key, default]) max(arg1, arg2, *args[, key])
Параметры:
iterable
– итерируемый объект,key
– должна быть функцией (принимает один аргумент), используется для порядка сравнения элементов итерируемого объекта. Функция вычисляется один раз,default
– значение по умолчанию, если итерируемый объект окажется пустым,arg1...argN
– позиционный аргумент,*args
– список позиционных аргументов.
Возвращаемое значение:
- наибольшее значение объекта.
Описание:
Функция max()
возвращает наибольшее значение элемента итерируемого объекта или самое большое из двух или более переданных позиционных аргументов.
- Если указан один позиционный аргумент, он должен быть итерируемым объектом (список, кортеж, словарь и т.д.).
- Если в функцию передается два или более позиционных аргумента, возвращается самый большой из них.
- В случае, когда максимальное значение имеют сразу несколько аргументов. Возвращает первый по порядку элемент с максимальным значением. Это согласуется с другими инструментами сохранения стабильности сортировки, такими как
sorted(iterable, key=keyfunc, reverse=True)[0]
иheapq.nlargest(1, iterable, key=keyfunc)
Аргумент key
– функция подобная той, которая используется в дополнительном методе списков list.sort()
. Функция принимает один аргумент и используется для упорядочивания элементов.
>>> x = ['4', '11', '6', '31'] # функция `max` сравнивает # числа как строки >>> max(x) '6' # функция 'key=lambda i: int(i)' применяется # к каждому элементу списка 'x', преобразуя # строки в тип 'int' и теперь функция `max` # сравнивает элементы списка как числа. >>> max(x, key=lambda i: int(i)) '31' # или другое применение функции 'key' # выбор списка с наибольшей суммой элементов >>> max([1,2,3,4], [3,4,5], key=sum) [3, 4, 5]
Аргумент default
по умолчанию указывает объект, который нужно вернуть, если предоставленный итерируемый объект пуст. Если итерация пуста и значение по умолчанию не указано, то возникает ошибка ValueError
.
# Значение по умолчанию >>> max([], default=10) 10
Функция max()
сравнивает элементы, используя оператор <
. Поэтому, все передаваемые в них значения должны быть сопоставимы друг с другом и одного типа, иначе бросается исключение TypeError
При передаче в качестве аргумента текстовых строк, байтовых строк или байтовых массивов, а так же списка символов, максимальное значение будет выбираться исходя из порядка следования символов, в таблице соответствующей кодировки.
>>> x = list('abcdifgh') >>> max(x) # 'i'
Изменено в Python 3.8: Аргумент key
может быть None
.
Примеры поиска максимального значения в последовательности.
- Нахождение самой длинной строки в списке строк;
- Нахождение максимального значения в списке строк, записанных как целые числа;
- Нахождения максимального значения в строке, которая состоит из чисел и строк;
- Определение индекса у максимального значения в списке;
- Выбор максимального значения для ключа или значения в словаре;
- Нахождение списка с наибольшей суммой элементов в списке списков;
- Нахождение списка с наибольшим количеством элементов в списке списков.
# использование позиционных аргументов >>> max(5, 3, 6, 5, 6) # 6 # использование в качестве аргумента - список >>> max([1.2, 1.3, 1.5, 2, 5.52]) # 5.52 # комбинирование позиционных аргументов и списка # при передаче списка 'x' происходит его распаковка >>> x = (1.2, 1.3, 1.5, 2, 5.52) >>> max(5, 3, 5, *x) # 5,52
Нахождение самой длинной строки в списке строк.
Найдем самую длинную строку. В качестве ключевой функции используем len()
. Она посчитает количество символов в строке каждого элемента списка строк, а функция max()
выберет максимальное число. Строки можно передать например как позиционные аргументы, так и списком ['Jul', 'John', 'Vicky']
, результат будет тот же.
>>> line = ['Jul', 'John', 'Vicky'] >>> max(line, key=len) # 'Vicky'
Нахождение max()
в списке строк, записанных как целые числа.
Есть список строк чисел и необходимо найти максимум, как если бы они были целыми числами? Если применить функцию max()
к исходному списку “как есть”, то она выберет наибольшее значение списка исходя из лексикографической сортировки. Для нахождения максимума, как числа, применим функцию lambda i: int(i)
в качестве ключа key
, которая “на лету” преобразует элементы списка в целые числа, тогда функция max()
выберет то что нам нужно.
>>> x = ['4', '11', '6', '31'] >>> max(x) # '6' >>> max(x, key = lambda i: int(i)) # '31'
Нахождения max()
в строке, которая состоит из чисел и строк.
Что бы найти максимум в строке, которая состоит из чисел и строк, необходимо сначала разделить исходную строку на список подстрок. Используем приемы, описанные в примерах функции sum()
:
- по разделителю, например пробелу
' '
или';'
методом строкиstr.split()
, - вытащить все цифры из исходной строки при помощи функцией
re.findall()
.
Затем в цикле перебрать полученный список и все строки с цифрами преобразовать в соответствующие числовые типы и уже потом применить функцию
# исходная строка >>> line = '12; 12,5; 14; один; 15.6; два' # способы преобразования строки в список строк # 1 способ по разделителю ';' >>> line.split(';') # ['12', ' 12,5', ' 14', ' один', ' 15.6', ' два'] # 2 способ по регулярному выражению >>> import re >>> match = re.findall(r'[d.?,?]+', line) >>> list(match) # ['12', '12,5', '14', '15.6']
Далее будем работать с более сложным списком, полученным 1 способом, где встречаются слова. И так, имеем список строк с цифрами и другими строками. Стоит задача: преобразовать строки с цифрами в соответствующие числовые типы и отбросить строки со словами, что бы потом найти максимум.
Задача усложняется тем, что вещественные числа в строках записаны как через запятую, так и через точку. Для необходимых проверок и преобразований определим функцию str_to_num()
.
>>> def str_to_num(str, chars=['.', ',']): ... # убираем начальные и конечные пробелы ... str = str.strip() ... if (any(char in str for char in chars) and ... str.replace('.', '').replace(',', '').isdigit()): ... # если в строке есть точка или запятая и при их замене на '' ... # строка состоит только из цифр то это тип float ... return float(str.replace(',', '.')) ... elif str.isdigit(): ... # если строка состоит только из цифр то это тип int ... return int(str) # полученный список строк 1-м способом >>> str_list = ['12', ' 12,5', ' 14', ' один', ' 15.6', ' два'] # новый список чисел, где будем искать максимум >>> num_list = [] >>> for i in str_list: ... # применим функцию преобразования строки в число ... n = str_to_num(i) ... if n is not None: ... # если функция возвращает число, ... # то добавляем в новый список ... num_list.append(str_to_num(i)) >>> num_list # [12, 12.5, 14, 15.6] >>> max(num_list) # 15.6
Определение индекса у максимального значения в списке.
Допустим есть список чисел и стоит задача, определить индекс максимального значения в этом списке. Для решения этой задачи необходимо пронумеровать список, т.е. создать кортеж – индекс/число, а затем найти максимум, используя в качестве ключа key=lambda i : i[1]
.
>>> lst = [1, 5, 3, 6, 9, 7] # пронумеруем список >>> lst_num = list(enumerate(lst, 0)) >>> lst_num # [(0, 1), (1, 5), (2, 3), (3, 6), (4, 9), (5, 7)] # найдем максимум (из второго значения кортежей) >>> t_max = max(lst_num, key=lambda i : i[1]) >>> t_max # (4, 9) # индекс максимального значения >>> t_max[0] # 4
Нахождение max()
для ключа или значения в словаре dict
.
Допустим есть словарь, задача: найти максимальное значение ключа или самого значения ключа и вывести эту пару.
# имеем словарь >>> d = {1: 3, 2: 4, 1: 9, 4: 1} # преобразуем его в список отображение >>> key_val = d.items() # преобразуем отображение в список # кортежей (ключ, значение) >>> key_val_list = list(key_val) # [(1, 9), (2, 4), (4, 1)]
По умолчанию, при нахождении максимального элемента из списка кортежей будет выбираться кортеж, у которого наибольшее значение имеет ключ исходного словаря (первый элемент в кортеже).
Но если необходимо получить пару (key, value)
, у которого наибольшее значение имеет значение ключа (второй элемент), то для этого нужно применить лямбда-функцию lambda i : i[1]
в качестве аргумента key
функции max()
, которая укажет, из какого элемента кортежа выбирать наибольшее значение.
# происходит сравнение по # первым элементам кортежа >>> kv = max(key_val_list) >>> kv # (4, 1) # максимальное значение ключа в словаре >>> kv[0] # 4 # меняем порядок сравнения >>> kv = max(key_val_list, key=lambda i : i[1]) >>> kv # (1, 9) # максимальное значение в словаре >>> kv[1] # 9 # ключ этого значения в словаре >>> kv[0] # 1 # получаем максимальное значение из словаря >>> d[kv[0]] # 9
Нахождение списка с наибольшей суммой элементов в списке списков.
Для выполнения данной задачи, используем функцию max()
, а в качестве ключевой функции применим встроенную функцию sum()
.
# исходный список >>> lst = [[1, 2, 3], [4, 5], [1, 3, 4, 5], [10, 20]] # выбираем список с наибольшей суммой элементов >>> max(lst, key=sum) # [10, 20]
Выбор списка с наибольшим количеством элементов из списка списков.
Для выполнения данной задачи, используем функцию max()
, а в качестве ключевой функции применим встроенную функцию len()
.
# исходный список >>> lst = [[1, 2, 3], [4, 5], [1, 3, 4, 5], [10, 20]] # выбираем список с наибольшим количеством элементов >>> max(lst, key=len) # [1, 3, 4, 5]
Write the function largestNumber(text)
that takes a string of text and returns the largest int value that occurs within that text, or None
if no such value occurs.
For example:
largestNumber("I saw 3 dogs, 17 cats, and 14 cows!")
returns 17 (the int value 17, not the string “17”).
and
largestNumber("One person ate two hot dogs!")
returns None
(the value None
, not the string "None"
).
I tried using isdigit
function to separate out integer but how can I compare string?
J…S
5,0341 gold badge20 silver badges35 bronze badges
asked Feb 4, 2014 at 4:49
1
You can try using a regex, and then max
and map
functions:
result = [e for e in re.split("[^0-9]", "I saw 3 dogs, 17 cats, and 14 cows!") if e != '']
# list 'result' elements are strings: ['3', '17', '14'], so we use map(int, list) to get integers
print max(map(int, result))
Muhd
24k22 gold badges61 silver badges78 bronze badges
answered Feb 4, 2014 at 5:03
Christian TapiaChristian Tapia
33.5k7 gold badges55 silver badges73 bronze badges
You could also do
def largestNumber(in_str):
l=[int(x) for x in in_str.split() if x.isdigit()]
return max(l) if l else None
First you split in_str
based on space () with
split()
to get a list.
The ‘numbers’ in this list are identified using isdigit()
and converted to integers using int()
.
These numbers are stored in l
as a list.
The expression
max(l) if l else None
will give maximum value in l if l
is not empty and otherwise None
.
print(largestNumber("I saw 3 dogs, 17 cats, and 14 cows!"))
gives
17
and
print(largestNumber("One person ate two hot dogs!"))
gives
None
answered Nov 16, 2019 at 11:56
J…SJ…S
5,0341 gold badge20 silver badges35 bronze badges
Just Another solution:
def findLargestNumber(text):
ls = list()
for w in text.split():
try:
ls.append(int(w))
except:
pass
try:
return max(ls)
except:
return None
print findLargestNumber('I saw 3 dogs, 17 cats, and 14 cows!')
print findLargestNumber('I saw ')
Output:
17
None
answered Feb 4, 2014 at 6:43
James SapamJames Sapam
15.8k11 gold badges50 silver badges71 bronze badges
def findLargestNumber(text):
front = -1
li = []
for i in range(len(text)):
if front == -1:
if text[i].isdigit():
front = i
else:
continue
else:
if text[i].isdigit():
continue
else:
li.append(int(text[front:i+1]))
front = -1
return max(li)
print findLargestNumber('I saw 3 dogs, 17 cats, and 14 cows!')
J…S
5,0341 gold badge20 silver badges35 bronze badges
answered Feb 4, 2014 at 6:36
import re
def extractmax(str1):
nums=re.findall("d+",str1)
return max(nums)
d+
is used to look for a decimal or number with length greater than one, it is appended into the array nums
finally maximum value from nums
if generated.
J…S
5,0341 gold badge20 silver badges35 bronze badges
answered Aug 8, 2018 at 12:07
ravi tanwarravi tanwar
5985 silver badges16 bronze badges
The following worked for me, and it works great!
Increment number in the string and then print out the max number in string
- import re
import re
- Increase number in string
name = "name 1"
number = re.search(r'd+', str(name))
if number:
rx = r'(?<!d){}(?!d)'.format(number.group())
prefix = re.sub(rx, lambda x: str(int(x.group()) + 1), name)
print(prefix)
Instead of just printing this row directly “re.sub(rx, lambda x: str(int(x.group()) + 1), name)”
Store it in a variable, in my case prefix
That’s because you will get the updated value in the string and not the original
Store incremented variable “name” into a list
li = [int(prefix[5:])]
print("Largest name", max(li))
Keep in mind that index 5 is where the number is starting, you may need to adjust it depending on the string length
You can try to make 2 variables to see if the max method is working properly
answered Mar 18, 2021 at 12:55
HerkerHerker
5226 silver badges19 bronze badges
Python’s built-in min()
and max()
functions come in handy when you need to find the smallest and largest values in an iterable or in a series of regular arguments. Even though these might seem like fairly basic computations, they turn out to have many interesting use cases in real-world programing. You’ll try out some of those use cases here.
In this tutorial, you’ll learn how to:
- Use Python’s
min()
andmax()
to find smallest and largest values in your data - Call
min()
andmax()
with a single iterable or with any number of regular arguments - Use
min()
andmax()
with strings and dictionaries - Tweak the behavior of
min()
andmax()
with thekey
anddefault
arguments - Use comprehensions and generator expressions as arguments to
min()
andmax()
Once you have this knowledge under your belt, then you’ll be prepared to write a bunch of practical examples that will showcase the usefulness of min()
and max()
. Finally, you’ll code your own versions of min()
and max()
in pure Python, which can help you understand how these functions work internally.
To get the most out of this tutorial, you should have some previous knowledge of Python programming, including topics like for
loops, functions, list comprehensions, and generator expressions.
Getting Started With Python’s min()
and max()
Functions
Python includes several built-in functions that make your life more pleasant and productive because they mean you don’t need to reinvent the wheel. Two examples of these functions are min()
and max()
. They mostly apply to iterables, but you can use them with multiple regular arguments as well. What’s their job? They take care of finding the smallest and largest values in their input data.
Whether you’re using Python’s min()
or max()
, you can use the function to achieve two slightly different behaviors. The standard behavior for each is to return the minimum or maximum value through straightforward comparison of the input data as it stands. The alternative behavior is to use a single-argument function to modify the comparison criteria before finding the smallest and largest values.
To explore the standard behavior of min()
and max()
, you can start by calling each function with either a single iterable as an argument or with two or more regular arguments. That’s what you’ll do right away.
Calling min()
and max()
With a Single Iterable Argument
The built-in min()
and max()
have two different signatures that allow you to call them either with an iterable as their first argument or with two or more regular arguments. The signature that accepts a single iterable argument looks something like this:
min(iterable, *[, default, key]) -> minimum_value
max(iterable, *[, default, key]) -> maximum_value
Both functions take a required argument called iterable
and return the minimum and maximum values respectively. They also take two optional keyword-only arguments: default
and key
.
Here’s a summary of what the arguments to min()
and max()
do:
Argument | Description | Required |
---|---|---|
iterable |
Takes an iterable object, like a list, tuple, dictionary, or string | Yes |
default |
Holds a value to return if the input iterable is empty | No |
key |
Accepts a single-argument function to customize the comparison criteria | No |
Later in this tutorial, you’ll learn more about the optional default
and key
arguments. For now, just focus on the iterable
argument, which is a required argument that leverages the standard behavior of min()
and max()
in Python:
>>>
>>> min([3, 5, 9, 1, -5])
-5
>>> min([])
Traceback (most recent call last):
...
ValueError: min() arg is an empty sequence
>>> max([3, 5, 9, 1, -5])
9
>>> max([])
Traceback (most recent call last):
...
ValueError: max() arg is an empty sequence
In these examples, you call min()
and max()
with a list of integer numbers and then with an empty list. The first call to min()
returns the smallest number in the input list, -5
. In contrast, the first call to max()
returns the largest number in the list, or 9
. If you pass an empty iterator to min()
or max()
, then you get a ValueError
because there’s nothing to do on an empty iterable.
An important detail to note about min()
and max()
is that all the values in the input iterable must be comparable. Otherwise, you get an error. For example, numeric values work okay:
>>>
>>> min([3, 5.0, 9, 1.0, -5])
-5
>>> max([3, 5.0, 9, 1.0, -5])
9
These examples combine int
and float
numbers in the calls to min()
and max()
. You get the expected result in both cases because these data types are comparable.
However, what would happen if you mixed strings and numbers? Check out the following examples:
>>>
>>> min([3, "5.0", 9, 1.0, "-5"])
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'str' and 'int'
>>> max([3, "5.0", 9, 1.0, "-5"])
Traceback (most recent call last):
...
TypeError: '>' not supported between instances of 'str' and 'int'
You can’t call min()
or max()
with an iterable of noncomparable types as an argument. In this example, a function tries to compare a number to a string, which is like comparing apples and oranges. The end result it that you get a TypeError
.
Calling min()
and max()
With Multiple Arguments
The second signature of min()
and max()
allows you to call them with any number of arguments, provided that you use at least two arguments. This signature has the following form:
min(arg_1, arg_2[, ..., arg_n], *[, key]) -> minimum_value
max(arg_1, arg_2[, ..., arg_n], *[, key]) -> maximum_value
Again, these functions return the minimum and maximum values, respectively. Here’s the meaning of the arguments in the above signature:
Argument | Description | Required |
---|---|---|
arg_1, arg_2, ..., arg_n |
Accepts any number of regular arguments to compare | Yes (at least two of them) |
key |
Takes a single-argument function to customize the comparison criteria | No |
This variation of min()
or max()
doesn’t have a default
argument. You must provide at least two arguments in the call for the function to work correctly. So, a default
value isn’t required, because you’ll always have at least two values to compare in order to find the minimum or maximum.
To try out this alternative signature, run the following examples:
>>>
>>> min(3, 5, 9, 1, -5)
-5
>>> max(3, 5, 9, 1, -5)
9
You can call min()
or max()
with two or more regular arguments. Again, you’ll get the minimum or maximum value in the input data, respectively. The only condition is that the arguments must be comparable.
Using min()
and max()
With Strings and Iterables of Strings
By default, min()
and max()
can process values that are comparable. Otherwise, you get a TypeError
, as you’ve already learned. Up to this point, you’ve seen examples that use numeric values either in an iterable or as multiple regular arguments.
Using min()
and max()
with numeric values is arguably the most common and useful use case of these functions. However, you can also use the functions with strings and iterables of strings. In these cases, the alphabetical order of characters will decide the final result.
For example, you can use min()
and max()
to find the smallest and largest letters in some text. In this context, smallest means closest to the beginning of the alphabet, and largest means closest to the end of the alphabet:
>>>
>>> min("abcdefghijklmnopqrstuvwxyz")
'a'
>>> max("abcdefghijklmnopqrstuvwxyz")
'z'
>>> min("abcdWXYZ")
'W'
>>> max("abcdWXYZ")
'd'
As promised, in the first two examples, min()
returns 'a'
and max()
returns 'z'
. However, in the second pair of examples, min()
returns 'W'
and max()
returns 'd'
. Why? Because uppercase letters come before lowercase letters in Python’s default character set, UTF-8.
Using min()
or max()
with a string as an argument isn’t limited to just letters. You can use strings containing any possible characters in your current character set. For example, if you’re working with the set of ASCII characters only, then the smallest character is the character closest to the beginning of the ASCII table. In contrast, the largest character is the character closest to the end of the table.
With other character sets like UTF-8, min()
and max()
behave similarly:
>>>
>>> # UTF-8 characters
>>> min("abc123ñ")
'1'
>>> max("abc123ñ")
'ñ'
Behind the scenes, min()
and max()
use the character’s numeric value to find the minimum and maximum characters in the input string. For example, in the Unicode character table, the uppercase A
has a smaller numeric value than the lowercase a
:
>>>
>>> ord("A")
65
>>> ord("a")
97
Python’s built-in ord()
function takes a single Unicode character and returns an integer representing the Unicode code point of that character. In these examples, the code point for the uppercase "A"
is lower than the code point for the lowercase "a"
.
This way, when you call min()
and max()
with both letters, you get results that match the order of the underlying Unicode code points of these letters:
>>>
>>> min("aA")
'A'
>>> max("aA")
'a'
What makes "A"
smaller than "a"
? The quick answer is the letter’s Unicode code point. All characters that you can type on your keyboard, and many other characters, have their own code points in the Unicode table. Python uses these code points to determine the minimum and maximum character when it comes to using min()
and max()
.
Finally, you can also call min()
and max()
with iterables of strings or with multiple string arguments. Again, both functions will determine their return value by comparing the strings alphabetically:
>>>
>>> min(["Hello", "Pythonista", "and", "welcome", "world"])
'Hello'
>>> max(["Hello", "Pythonista", "and", "welcome", "world"])
'world'
To find the smallest or largest string in an iterable of strings, min()
and max()
compare all the strings alphabetically based on the code points of initial characters.
In the first example, the uppercase "H"
comes before "P"
, "a"
, and "w"
in the Unicode table. So, min()
immediately concludes that "Hello"
is the smallest string. In the second example, the lowercase "w"
comes after all the other strings’ initial letters.
Note that there are two words that start with "w"
, "welcome"
and "world"
. So, Python proceeds to look at the second letter of each word. The result is that max()
returns "world"
because "o"
comes after "e"
.
Processing Dictionaries With min()
and max()
When it comes to processing Python dictionaries with min()
and max()
, you need to consider that if you use the dictionary directly, then both functions will operate on the keys:
>>>
>>> prices = {
... "banana": 1.20,
... "pineapple": 0.89,
... "apple": 1.57,
... "grape": 2.45,
... }
>>> min(prices)
'apple'
>>> max(prices)
'pineapple'
In these examples, min()
returns the alphabetically smallest key in prices
, and max()
returns the largest one. You can get the same result using the .keys()
method on your input dictionary:
>>>
>>> min(prices.keys())
'apple'
>>> max(prices.keys())
'pineapple'
The only difference between this latter example and the previous one is that here, the code is more explicit and clear about what you’re doing. Anyone reading your code will quickly realize that you want to find the smallest and largest keys in the input dictionary.
Another common requirement would be to find the smallest and largest values in a dictionary. To continue with the prices
example, say you want to know the smallest and largest prices. In this situation, you can use the .values()
method:
>>>
>>> min(prices.values())
0.89
>>> max(prices.values())
2.45
In these examples, min()
goes through all the values in prices
and finds the minimum price. Similarly, max()
iterates over the values of prices
and returns the maximum price.
Finally, you can also use the .items()
method on the input dictionary to find the minimum and maximum key-value pairs:
>>>
>>> min(prices.items())
('apple', 1.57)
>>> max(prices.items())
('pineapple', 2.45)
In this case, min()
and max()
use Python’s internal rules to compare tuples and find the smallest and largest items in the input dictionary.
Python compares tuples item by item. For example, to determine if (x1, x2)
is greater than (y1, y2
), Python tests x1 > y1
. If this condition is True
, then Python concludes that the first tuple is greater than the second without checking the rest of the items. In contrast, if x1 < y1
, then Python concludes that the first tuple is less than the second.
Finally, if x1 == y1
, then Python compares the second pair of items using the same rules. Note that in this context, the first item of each tuple comes from the dictionary keys, and because dictionary keys are unique, the items can’t be equal. So, Python will never have to compare the second values.
Tweaking the Standard Behavior of min()
and max()
With key
and default
Up to this point, you’ve learned how min()
and max()
work in their standard form. In this section, you’ll learn how to tweak the standard behavior of both functions by using the key
and default
keyword-only arguments.
The key
argument to min()
or max()
allows you to provide a single-argument function that will be applied to every value in the input data. The goal is to modify the comparison criteria to use in finding the minimum or maximum value.
As an example of how this feature can be useful, say that you have a list of numbers as strings, and want to find the smallest and largest numbers. If you process the list directly with min()
and max()
, then you get the following results:
>>>
>>> min(["20", "3", "35", "7"])
'20'
>>> max(["20", "3", "35", "7"])
'7'
These may not be the results that you need or expect. You’re getting the smallest and largest strings based on Python’s string comparison rules rather than based on the actual numeric value of each string.
In that case, the solution is to pass the built-in int()
function as the key
argument to min()
and max()
, like in the following examples:
>>>
>>> min(["20", "3", "35", "7"], key=int)
'3'
>>> max(["20", "3", "35", "7"], key=int)
'35'
Great! Now the result of min()
or max()
depends on the numeric values of the underlying strings. Note that you don’t need to call int()
. You just pass int
without the pair of parentheses because key
expects a function object, or more accurately, a callable object.
The second keyword-only argument that allows you to customize the standard behavior of min()
or max()
is default
. Remember that this argument is only available when you call the function with a single iterable as an argument.
The job of default
is to provide a suitable default value as the return value of min()
or max()
when it’s called with an empty iterable:
>>>
>>> min([], default=42)
42
>>> max([], default=42)
42
In these examples, the input iterable is an empty list. The standard behavior is for min()
or max()
to raise a ValueError
complaining about the empty sequence argument. However, because you supply a value to default
, both functions now return this value instead of raising an exception and breaking your code.
Using min()
and max()
With Comprehensions and Generator Expressions
You can also call min()
or max()
with a list comprehension or generator expression as an argument. This feature comes in handy when you need to transform the input data right before finding the minimum or maximum transformed value.
When you feed a list comprehension into min()
or max()
, the resulting value will come from the transformed data rather than from the original data:
>>>
>>> letters = ["A", "B", "C", "X", "Y", "Z"]
>>> min(letters)
'A'
>>> min([letter.lower() for letter in letters])
'a'
>>> max(letters)
'Z'
>>> max([letter.lower() for letter in letters])
'z'
The second call to min()
takes a list comprehension as an argument. This comprehension transforms the original data in letters
by applying the .lower()
method to each letter. The final result is the lowercase "a"
, which isn’t present in the original data. Something similar happens with the examples covering max()
.
Note that using min()
or max()
with a list comprehension is similar to using the key
argument. The main difference is that with comprehensions, the final result is a transformed value, while with key
, the result comes from the original data:
>>>
>>> letters = ["A", "B", "C", "X", "Y", "Z"]
>>> min([letter.lower() for letter in letters])
'a'
>>> min(letters, key=str.lower)
'A'
In both examples, min()
uses .lower()
to somehow modify the comparison criteria. The difference is that the comprehension actually transforms the input data before doing the computation, so the resulting value comes from the transformed data rather than from the original.
List comprehensions create a complete list in memory, which is often a wasteful operation. This fact holds especially true if you don’t need the resulting list in your code anymore, which could be the case with min()
and max()
. So, it’s always more efficient to use a generator expression instead.
The syntax for generator expressions is almost the same as for list comprehensions:
>>>
>>> letters = ["A", "B", "C", "X", "Y", "Z"]
>>> min(letters)
'A'
>>> min(letter.lower() for letter in letters)
'a'
>>> max(letters)
'Z'
>>> max(letter.lower() for letter in letters)
'z'
The main syntax difference is that a generator expression uses parentheses instead of square brackets ([]
). Because a function call already requires parentheses, you just need to remove the square brackets from your comprehension-based examples, and you’re good to go. Unlike list comprehensions, generator expressions yield items on demand, which makes them memory efficient.
Putting Python’s min()
and max()
Into Action
So far, you’ve learned the basics of using min()
and max()
to find the smallest and largest values in an iterable or in a series of individual values. You learned how min()
and max()
work with different built-in Python data types, such as numbers, strings, and dictionaries. You also explored how to tweak the standard behavior of these functions and how to use them with list comprehensions and generator expressions.
Now you’re ready to start coding a few practical examples that will show you how to use min()
and max()
in your own code.
Removing the Smallest and Largest Numbers in a List
To kick things off, you’ll start with a short example of how to remove the minimum and maximum values from a list of numbers. To do that, you can call .remove()
on your input list. Depending on your needs, you’ll use min()
or max()
to select the value that you’ll remove from the underlying list:
>>>
>>> sample = [4, 5, 7, 6, -12, 4, 42]
>>> sample.remove(min(sample))
>>> sample
[4, 5, 7, 6, 4, 42]
>>> sample.remove(max(sample))
>>> sample
[4, 5, 7, 6, 4]
In these examples, the minimum and maximum values in sample
could be outlier data points that you want to remove so that they don’t affect your further analysis. Here, min()
and max()
provide the arguments to .remove()
.
Building Lists of Minimum and Maximum Values
Now say that you have a list of lists representing a matrix of numeric values, and you need to build lists containing the smallest and largest values from every row in the input matrix. To do this, you can use min()
and max()
along with a list comprehension:
>>>
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [min(x) for x in matrix]
[1, 4, 7]
>>> [max(x) for x in matrix]
[3, 6, 9]
The first comprehension iterates over the sublists in matrix
and uses min()
to build a list containing the smallest value from each sublist. The second comprehension does a similar task but uses max()
to create a list containing the largest values from the sublists in matrix
.
Even though min()
and max()
provide a quick way to deal with the examples in this section, the NumPy library is highly recommended when it comes to processing matrixes in Python because NumPy has specific and optimized tools for the job.
Clipping Values to the Edges of an Interval
Sometimes you have a list of numeric values and want to clip them to the edges or limits of a given interval. For example, if a given value is greater than the interval’s upper limit, then you need to convert it down to that limit. To do this operation, you can use min()
.
Wait! Why min()
? You’re dealing with the large values, aren’t you? The point is that you need to compare each large value to the interval’s upper limit and then choose the smaller of the two. You’ll essentially set all large values to a prescribed upper limit:
>>>
>>> # Clip values to the largest interval's edge
>>> upper = 100
>>> numbers = [42, 78, 200, -230, 25, 142]
>>> [min(number, upper) for number in numbers]
[42, 78, 100, -230, 25, 100]
The call to min()
compares every number to the interval’s upper limit. If the target number is greater than the limit, then min()
returns the limit. The net effect is that all the values that are greater than the limit are now clipped to it. In this example, the numbers 200
and 142
are clipped to 100
, which is the interval’s upper limit.
In contrast, if you want to clip small values to the interval’s lower limit, then you can use max()
, like in the following example:
>>>
>>> # Clip values to the smallest interval's edge
>>> lower = 10
>>> numbers = [42, 78, 200, -230, 25, 142]
>>> [max(number, lower) for number in numbers]
[42, 78, 200, 10, 25, 142]
This call to max()
clips the small values to the interval’s lower limit. To do this clipping, max()
compares the current number and the interval’s limit to find the maximum value. In the example, -230
is the only number that gets clipped.
Finally, you can run both operations in one go by combining min()
and max()
. Here’s how to do it:
>>>
>>> # Clipping values to 10 - 100
>>> lower, upper = 10, 100
>>> numbers = [42, 78, 100, -230, 25, 142]
>>> [max(min(number, upper), lower) for number in numbers]
[42, 78, 100, 10, 25, 100]
To clip all the values that fall outside the interval’s limits, this comprehension combines min()
and max()
. The call to min()
compares the current value to the interval’s upper limit, while the call to max()
compares the result to the lower limit. The final result is that values lower than or greater than the corresponding limit are clipped to the limit itself.
This comprehension works similarly to the clip()
function from NumPy, which takes an array and the limits of the target interval, then it clips all values outside the interval to the interval’s edges.
Finding the Closest Points
Now say that you have a list of tuples containing pairs of values that represent Cartesian points. You want to process all these pairs of points and find out which pair has the smallest distance between points. In this situation, you can do something like the following:
>>>
>>> import math
>>> point_pairs = [
... ((12, 5), (9, 4)),
... ((2, 5), (3, 7)),
... ((4, 11), (15, 2))
... ]
>>> min(point_pairs, key=lambda points: math.dist(*points))
((2, 5), (3, 7))
In this example, you first import math
to get access to dist()
. This function returns the Euclidean distance between two points, p and q, each given as a sequence of coordinates. The two points must have the same number of dimensions.
The min()
function works its magic through its key
argument. In this example, key
takes a lambda
function that computes the distance between two points. This function becomes the comparison criteria for min()
to find the pair of points with the minimal distance between points.
In this example, you need a lambda
function because key
expects a single-argument function, while math.dist()
requires two arguments. So, the lambda
function takes a single argument, points
, and then unpacks it into two arguments to feed into math.dist()
.
Identifying Cheap and Expensive Products
Now say you have a dictionary with the names and prices of several products, and you want to identify the cheapest and most expensive products. In this situation, you can use .items()
and an appropriate lambda
function as the key
argument:
>>>
>>> prices = {
... "banana": 1.20,
... "pineapple": 0.89,
... "apple": 1.57,
... "grape": 2.45,
... }
>>> min(prices.items(), key=lambda item: item[1])
('pineapple', 0.89)
>>> max(prices.items(), key=lambda item: item[1])
('grape', 2.45)
In this example, the lambda
function takes a key-value pair as an argument and returns the corresponding value so that min()
and max()
have proper comparison criteria. As a result, you get a tuple with the cheapest and most expensive products in the input data.
Finding Coprime Integer Numbers
Another interesting example of using min()
to solve a real-world problem is when you need to figure out if two numbers are coprime. In other words, you need to know if your numbers’ only common divisor is 1
.
In that situation, you can code a Boolean-valued or predicate function like the following:
>>>
>>> def are_coprime(a, b):
... for i in range(2, min(a, b) + 1):
... if a % i == 0 and b % i == 0:
... return False
... return True
...
>>> are_coprime(2, 3)
True
>>> are_coprime(2, 4)
False
In this code snippet, you define are_coprime()
as a predicate function that returns True
if the input numbers are coprime. If the numbers aren’t coprime, then the function returns False
.
The function’s main component is a for
loop that iterates over a range
of values. To set the upper limit for this range
object, you use min()
with the input numbers as arguments. Again, you’re using min()
to set the upper limit of some interval.
Timing Different Implementations of Your Code
You can also use min()
to compare several of your algorithms, evaluate their execution times, and determine which algorithm is the most efficient. The example below uses timeit.repeat()
to measure the execution times for two different ways of building a list containing the square values of the numbers from 0
to 99
:
>>>
>>> import timeit
>>> min(
... timeit.repeat(
... stmt="[i ** 2 for i in range(100)]",
... number=1000,
... repeat=3
... )
... )
0.022141209003166296
>>> min(
... timeit.repeat(
... stmt="list(map(lambda i: i ** 2, range(100)))",
... number=1000,
... repeat=3
... )
... )
0.023857666994445026
The call to timeit.repeat()
runs a string-based statement a given number of times. In these examples, the statement is repeated three times. The call to min()
returns the smallest execution time from the three repetitions.
By combining min()
, repeat()
, and other Python timer functions, you can get an idea of which of your algorithms is most efficient in terms of execution time. The example above shows that list comprehensions can be a little bit faster than the built-in map()
function when it comes to building new lists.
Exploring the Role of .__lt__()
and .__gt__()
in min()
and max()
As you’ve learned so far, the built-in min()
and max()
functions are versatile enough to work with values of various data types, such as numbers and strings. The secret behind this flexibility is that min()
and max()
embrace Python’s duck typing philosophy by relying on the .__lt__()
and .__gt__()
special methods.
These methods are part of what Python calls rich comparison methods. Specifically, .__lt__()
and .__gt__()
support the less than (<
) and greater than (>
) operators, respectively. What’s the meaning of support here? When Python finds something like x < y
in your code, it internally does x.__lt__(y)
.
The takeaway is that you can use min()
and max()
with values of any data type that implements .__lt__()
and .__gt__()
. That’s why these functions work with values of all Python’s built-in data types:
>>>
>>> "__lt__" in dir(int) and "__gt__" in dir(int)
True
>>> "__lt__" in dir(float) and "__gt__" in dir(float)
True
>>> "__lt__" in dir(str) and "__gt__" in dir(str)
True
>>> "__lt__" in dir(list) and "__gt__" in dir(list)
True
>>> "__lt__" in dir(tuple) and "__gt__" in dir(tuple)
True
>>> "__lt__" in dir(dict) and "__gt__" in dir(dict)
True
Python’s built-in data types implement the .__lt__()
and .__gt__()
special methods. So, you can feed any of these data types into min()
and max()
, with the only condition being that the involved data types are comparable.
You can also make instances of your custom classes compatible with min()
and max()
. To achieve this, you need to provide your own implementations of .__lt__()
and .__gt__()
. Consider the following Person
class as an example of this compatibility:
# person.py
from datetime import date
class Person:
def __init__(self, name, birth_date):
self.name = name
self.birth_date = date.fromisoformat(birth_date)
def __repr__(self):
return (
f"{type(self).__name__}"
f"({self.name}, {self.birth_date.isoformat()})"
)
def __lt__(self, other):
return self.birth_date > other.birth_date
def __gt__(self, other):
return self.birth_date < other.birth_date
Note that the implementation of .__lt__()
and .__gt__()
requires an argument that’s typically named other
. This argument represents the second operand in the underlying comparison operations. For example, in an expression like x < y
, you’ll have that x
will be self
and y
will be other
.
In this example, .__lt__()
and .__gt__()
return the result of comparing two people’s .birth_date
attributes. Here’s how this works in practice:
>>>
>>> from person import Person
>>> jane = Person("Jane Doe", "2004-08-15")
>>> john = Person("John Doe", "2001-02-07")
>>> jane < john
True
>>> jane > john
False
>>> min(jane, john)
Person(Jane Doe, 2004-08-15)
>>> max(jane, john)
Person(John Doe, 2001-02-07)
Cool! You can process Person
objects with min()
and max()
because the class provides implementation of .__lt__()
and .__gt__()
. The call to min()
returns the youngest person, and the call to max()
returns the oldest.
Note that if a given custom class doesn’t provide these methods, then its instances won’t support min()
and max()
operations:
>>>
>>> class Number:
... def __init__(self, value):
... self.value = value
...
>>> x = Number(21)
>>> y = Number(42)
>>> min(x, y)
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'Number' and 'Number'
>>> max(x, y)
Traceback (most recent call last):
...
TypeError: '>' not supported between instances of 'Number' and 'Number'
Because this Number
class doesn’t provide suitable implementations of .__lt__()
and .__gt__()
, min()
and max()
respond with a TypeError
. The error message tells you that the comparison operations aren’t supported in your current class.
Emulating Python’s min()
and max()
Up to this point, you’ve learned how Python’s min()
and max()
functions work. You’ve used them to find the smallest and largest values among several numbers, strings, and more. You know how to call these functions either with a single iterable as an argument or with an undefined number of regular arguments. Finally, you’ve coded a series of practical examples that approach real-world problems using min()
and max()
.
Although Python kindly provides you with min()
and max()
to find the smallest and largest values in your data, learning how to do this computation from scratch is a helpful exercise that can improve your logical thinking and your programming skills.
In this section, you’ll learn how to find minimum and maximum values in your data. You’ll also learn how to implement your own versions of min()
and max()
.
Understanding the Code Behind min()
and max()
To find the minimum value in a small list of numbers as a human, you’d normally check the numbers and implicitly compare all of them in your mind. Yes, your brain is amazing! However, computers aren’t that smart. They need detailed instructions to accomplish any task.
You’ll have to tell your computer to iterate over all the values while comparing them in pairs. In the process, the computer has to take note of the current minimum value in each pair until the list of values is processed entirely.
This explanation may be hard to visualize, so here’s a Python function that does the work:
>>>
>>> def find_min(iterable):
... minimum = iterable[0]
... for value in iterable[1:]:
... if value < minimum:
... minimum = value
... return minimum
...
>>> find_min([2, 5, 3, 1, 9, 7])
1
In this code snippet, you define find_min()
. This function assumes that iterable
isn’t empty and that its values are in an arbitrary order.
The function treats the first value as a tentative minimum
. Then the for
loop iterates over the rest of the elements in the input data.
The conditional statement compares the current value
to the tentative minimum
in the first iteration. If the current value
is smaller than minimum
, then the conditional updates minimum
accordingly.
Each new iteration compares the current value
to the updated minimum
. When the function reaches the end of iterable
, minimum
will hold the smallest value in the input data.
Cool! You’ve coded a function that finds the smallest value in an iterable of numbers. Now revisit find_min()
and think of how you’d code a function to find the largest value. Yes, that’s it! You just have to change the comparison operator from less than (<
) to greater than (>
), and probably rename the function and some local variables to prevent confusion.
Your new function can look something like this:
>>>
>>> def find_max(iterable):
... maximum = iterable[0]
... for value in iterable[1:]:
... if value > maximum:
... maximum = value
... return maximum
...
>>> find_max([2, 5, 3, 1, 9, 7])
9
Note that find_max()
shares most of its code with find_min()
. The most important difference, apart from naming, is that find_max()
uses the greater than operator (>
) instead of the less than operator (<
).
As an exercise, you can think of how to avoid repetitive code in find_min()
and find_max()
following the DRY (don’t repeat yourself) principle. This way, you’ll be ready to emulate the complete behavior of min()
and max()
using your Python skills, which you’ll tackle in just a moment.
Before diving in, you need to be aware of the knowledge requirements. You’ll be combining topics like conditional statements, exception handling, list comprehensions, definite iteration with for
loops, and *args
and optional arguments in functions.
If you feel that you don’t know everything about these topics, then don’t worry. You’ll learn by doing. If you get stuck, then you can go back and review the linked resources.
Planning Your Custom min()
and max()
Versions
To write your custom implementations of min()
and max()
, you’ll start by coding a helper function that’s able to find the smallest or largest value in the input data, depending on the arguments you use in the call. Of course, the helper function will especially depend on the operator used for comparing the input values.
Your helper function will have the following signature:
min_max(*args, operator, key=None, default=None) -> extreme_value
Here’s what each argument does:
Argument | Description | Required |
---|---|---|
*args |
Allows you to call the function with either an iterable or any number of regular arguments | Yes |
operator |
Holds the appropriate comparison operator function for the computation at hand | Yes |
key |
Takes a single-argument function that modifies the function’s comparison criteria and behavior | No |
default |
Stores a default value to return when you call the function with an empty iterable | No |
The body of min_max()
will start by processing *args
to build a list of values. Having a standardized list of values will allow you to write the required algorithm to find the minimum and maximum values in the input data.
Then the function needs to deal with the key
and default
arguments before computing the minimum and maximum, which is the final step inside min_max()
.
With min_max()
in place, the final step is to define two independent functions on top of it. These functions will use appropriate comparison operator functions to find the minimum and maximum values, respectively. You’ll learn more about operator functions in a moment.
Standardizing the Input Data From *args
To standardize the input data, you need to check if the user is providing a single iterable or any number of regular arguments. Fire up your favorite code editor or IDE and create a new Python file called min_max.py
. Then add the following piece of code to it:
# min_max.py
def min_max(*args, operator, key=None, default=None):
if len(args) == 1:
try:
values = list(args[0]) # Also check if the object is iterable
except TypeError:
raise TypeError(
f"{type(args[0]).__name__} object is not iterable"
) from None
else:
values = args
Here, you define min_max()
. The function’s first portion standardizes the input data for further processing. Because the user will be able to call min_max()
with either a single iterable or with several regular arguments, you need to check the length of args
. To do this check, you use the built-in len()
function.
If args
holds only one value, then you need to check if that argument is an iterable object. You use list()
, which implicitly does the check and also turns the input iterable into a list.
If list()
raises a TypeError
, then you catch it and raise your own TypeError
to inform the user that the provided object isn’t iterable, just like min()
and max()
do in their standard form. Note that you use the from None
syntax to hide away the traceback of the original TypeError
.
The else
branch runs when args
holds more than one value, which handles the cases where the user calls the function with several regular arguments instead of with a single iterable of values.
If this conditional doesn’t ultimately raise a TypeError
, then values
will hold a list of values that may be empty. Even if the resulting list is empty, it’s now clean and ready for continuing the process of finding its minimum or maximum value.
Processing the default
Argument
To continue writing min_max()
, you can now process the default
argument. Go ahead and add the following code to the end of the function:
# min_max.py
# ...
def min_max(*args, operator, key=None, default=None):
# ...
if not values:
if default is None:
raise ValueError("args is an empty sequence")
return default
In this code snippet, you define a conditional to check if values
holds an empty list. If that’s the case, then you check the default
argument to see if the user provided a value for it. If default
is still None
, then a ValueError
is raised. Otherwise, default
gets returned. This behavior emulates the standard behavior of min()
and max()
when you call them with empty iterables.
Handling the Optional key
Function
Now you need to process the key
argument and prepare the data for finding the smallest and largest values according to the provided key
. Go ahead and update min_max()
with the following code:
# min_max.py
# ...
def min_max(*args, operator, key=None, default=None):
# ...
if key is None:
keys = values
else:
if callable(key):
keys = [key(value) for value in values]
else:
raise TypeError(f"{type(key).__name__} object is not a callable")
You start this code fragment with a conditional that checks if the user hasn’t provided a key
function. If they haven’t, then you create a list of keys directly from your original values
. You’ll use these keys as comparison keys in computing the minimum and maximum.
On the other hand, if the user has provided a key
argument, then you need to make sure that the argument is actually a function or callable object. To do this, you use the built-in callable()
function, which returns True
if its argument is a callable and False
otherwise.
Once you’re sure that key
is a callable object, then you build the list of comparison keys by applying key
to each value in the input data.
Finally, if key
isn’t a callable object, then the else
clause runs, raising a TypeError
, just like min()
and max()
do in a similar situation.
Finding Minimum and Maximum Values
The last step to finish your min_max()
function is to find the minimum and maximum values in the input data, just like min()
and max()
do. Go ahead and wrap up min_max()
with the following code:
# min_max.py
# ...
def min_max(*args, operator, key=None, default=None):
# ...
extreme_key, extreme_value = keys[0], values[0]
for key, value in zip(keys[1:], values[1:]):
if operator(key, extreme_key):
extreme_key = key
extreme_value = value
return extreme_value
You set the extreme_key
and extreme_value
variables to the first value in keys
and in values
, respectively. These variables will provide the initial key and value for computing the minimum and maximum.
Then you loop over the remaining keys and values in one go using the built-in zip()
function. This function will yield key-value tuples by combining the values in your keys
and values
lists.
The conditional inside the loop calls operator
to compare the current key
to the tentative minimum or maximum key stored in extreme_key
. At this point, the operator
argument will hold either lt()
or gt()
from the operator
module, depending on if you want to find the minimum or maximum value, respectively.
For example, when you want to find the smallest value in the input data, operator
will hold the lt()
function. When you want to find the largest value, operator
will hold gt()
.
Every loop iteration compares the current key
to the tentative minimum or maximum key and updates the values of extreme_key
and extreme_value
accordingly. At the end of the loop, these variables will hold the minimum or maximum key and its corresponding value. Finally, you just need to return the value in extreme_value
.
Coding Your Custom min()
and max()
Functions
With the min_max()
helper function in place, you can define your custom versions of min()
and max()
. Go ahead and add the following functions to the end of your min_max.py
file:
# min_max.py
from operator import gt, lt
# ...
def custom_min(*args, key=None, default=None):
return min_max(*args, operator=lt, key=key, default=default)
def custom_max(*args, key=None, default=None):
return min_max(*args, operator=gt, key=key, default=default)
In this code snippet, you first import gt()
and lt()
from the operator
module. These functions are the functional equivalent of the greater than (>
) and less than (<
) operators, respectively. For example, the Boolean expression x < y
is equivalent to the function call lt(x, y)
. You’ll use these functions to provide the operator
argument to your min_max()
.
Just like min()
and max()
, custom_min()
and custom_max()
take *args
, key
, and default
as arguments and return the minimum and maximum values, respectively. To perform the computation, these functions call min_max()
with the required arguments and with the appropriate comparison operator
function.
In custom_min()
, you use lt()
to find the smallest value in the input data. In custom_max()
, you use gt()
to get the largest value.
Click the collapsible section below if you want to get the entire content of your min_max.py
file:
# min_max.py
from operator import gt, lt
def min_max(*args, operator, key=None, default=None):
if len(args) == 1:
try:
values = list(args[0]) # Also check if the object is iterable
except TypeError:
raise TypeError(
f"{type(args[0]).__name__} object is not iterable"
) from None
else:
values = args
if not values:
if default is None:
raise ValueError("args is an empty sequence")
return default
if key is None:
keys = values
else:
if callable(key):
keys = [key(value) for value in values]
else:
raise TypeError(f"{type(key).__name__} object is not a callable")
extreme_key, extreme_value = keys[0], values[0]
for key, value in zip(keys[1:], values[1:]):
if operator(key, extreme_key):
extreme_key = key
extreme_value = value
return extreme_value
def custom_min(*args, key=None, default=None):
return min_max(*args, operator=lt, key=key, default=default)
def custom_max(*args, key=None, default=None):
return min_max(*args, operator=gt, key=key, default=default)
Cool! You’ve finished coding your own versions of min()
and max()
in Python. Now go ahead and give them a try!
Conclusion
Now you know how to use Python’s built-in min()
and max()
functions to find the smallest and largest values in an iterable or in a series of two or more regular arguments. You also learned about a few other characteristics of min()
and max()
that can make them useful in your day-to-day programming.
In this tutorial, you learned how to:
- Find the smallest and largest values using Python’s
min()
andmax()
, respectively - Call
min()
andmax()
with a single iterable and with several regular arguments - Use
min()
andmax()
with strings and dictionaries - Customize the behavior of
min()
andmax()
withkey
anddefault
- Feed comprehensions and generator expressions into
min()
andmax()
Additionally, you’ve coded a handful of practical examples using min()
and max()
to approach real-world problems that you might run into while coding. You’ve also a written custom version of min()
and max()
in pure Python, a nice learning exercise that helped you understand the logic behind these built-in functions.
The main reason python is considered one of the easiest to learn and user-friendly languages because it offers different types of built-in functions that are super useful. One such function is the python max function. If you already use it in your program, you would know how many times it has made our life easy.
Python max function is an inbuilt global function that is used to fetch the maximum value from a list, tuple, or dictionary. Sometimes, we need to fetch the highest values from the list and have a check on them. With the help of max(), we can do it easily without creating a new function.
Let’s understand how this works and some interesting use cases. Before that, let’s have a look at how it works.
Usage of Python Max Function
When we want to find the largest element among the given elements or list of items, or maybe we want to find the list among many lists that contain the highest item, even we can find the string starting with the highest value alphabetically.
Syntax-
- max(iterable, *[, default=obj, key=func]) -> value
Here, iterable refers to object like list,string,tuple,etc.
default= If we pass an iterable without any values in the max function it will result in the following error-
max() arg is an empty sequence
So, we can pass a default parameter with any value we want. For example-
print(max([],default="No value"))
Output:
No value
key= We will understand this parameter with an example.
list1=["a","b","c","Z"] print(max(list1))
Output:
c
In the example above, alphabetically ‘Z’ is the largest value, but as the ASCII value of ‘Z’ is lesser than that of ‘c’, we have got the output as ‘c’. To solve this problem, we will make every value in the same form using the key parameter. Let’s see how-
list1=["a","b","c","Z"] print (max(list1, key=str.lower))
Output:
Z
- max (arg1, arg2, *args, *[, key=func]) -> value
When we do not need to pass the iterable and just the value in the arguments, we use this syntax.
Output:
6
There is no default parameter and the key parameter is same as above.
Examples of Python Max Function
- Finding the highest value in a dictionary-
dict1 = {'a':5,'b':1,'c':9,'d':2} print(max (dict1.values()))
Output:
9
- We are finding the largest value in the string.
Output:
w
- Find the largest key in the dictionary
Dict1={1:’c’,2:’b’,3:’a’} print(max(Dict1))
Output:
3
- If we want to find the string with maximum length-
print(max("ashwini","mandani","max","function",key=len))
Output:
function
- Suppose we want to find the list that has the highest element in it
list1=[1,2,3] list2=[3,4,5] list3=[5,6,1] print(max(list1,list2,list3))
Output:
[5,6,1]
- Similarly, if we want to find the list with most number of elements –
list1=[1,2,3,5] list2=[3,4,5] list3=[5,6,1] print(max(list1, list2, list3, key=len))
Output:
[1, 2, 3, 5]
- We can also apply max function on a pandas Series named series.
0 643.09 1 656.22 2 487.29 3 1504.75 4 1275.46 Name: size, dtype: float64
Output:
1504.75
Now that we have learned how to use python max function with various data types. Let us implement our own max function.
Implementing our own python max function-
Without Recursion
def max(list1): for i in range(0,len(list1)-1): for j in range(0,len(list1)-i-1): if list1[j] > list1[j+1]: list1[j],list1[j+1]=list1[j+1],list1[j] return list1[-1]
list1=[7, 5, 9, 6, 3] print(max(list1))
Output:
9
With Recursion-
Let’s look at how we can create our own max function with recursion. We can only pass a single list with multiple elements.
def recursive_max(list1): if list1[1:]: if list1[0] > rec_max(list1[1:]): return list1[0] else: return rec_max(list1[1:]) elif not list1: return else: return list1[0]
list1 = [12, 56, 23, 80] print(recursive_max(list1))
Output:
80
list1 = ['a','b','c','d'] print(recursive_max(list1))
Output:
d
Some Common Errors while using Python Max Function
TypeError– This is a very common error we face. This error generally occurs when in the max function we pass incompatible data types with each other like string and integer or float and string.
For example-
Output:
TypeError- '>' not supported between instances of 'int' and 'str'
Also, if we don’t pass any value in the max function, we get this error. For this we use default parameter.
The Complimentary method of python max function is min function, which is used to find the minimum value.
Output:
1
Must Read:
- How to Convert String to Lowercase in
- How to Calculate Square Root
- User Input | Input () Function | Keyboard Input
- Best Book to Learn Python
Conclusion
The time complexity of the python max function is O(n). Unlike max functions in other programming languages like C++, it offers a variety of uses. We can apply it on the string, which is not possible in other languages. These types of built-in functions make python a great language.
Try to run the programs on your side and let me know if you have any queries.
Happy Coding!
В этой статье мы научимся находить максимальное значение в списке на Python. Для всестороннего понимания вопроса мы рассмотрим использование некоторых встроенных функций, простые подходы, а также небольшие реализации известных алгоритмов.
Сначала давайте вкратце рассмотрим, что такое список в Python и как найти в нем максимальное значение или просто наибольшее число.
В Python есть встроенный тип данных под названием список (list). По своей сути он сильно напоминает массив. Но в отличие от последнего данные внутри списка могут быть любого типа (необязательно одного): он может содержать целые числа, строки или значения с плавающей точкой, или даже другие списки.
Хранимые в списке данные определяются как разделенные запятыми значения, заключенные в квадратные скобки. Списки можно определять, используя любое имя переменной, а затем присваивая ей различные значения в квадратных скобках. Он является упорядоченным, изменяемым и допускает дублирование значений. Например:
list1 = ["Виктор", "Артем", "Роман"]
list2 = [16, 78, 32, 67]
list3 = ["яблоко", "манго", 16, "вишня", 3.4]
Далее мы рассмотрим возможные варианты кода на Python, реализующего поиск наибольшего элемента в списке, состоящем из сравниваемых элементов. В наших примерах будут использоваться следующие методы/функции:
- Встроенная функция
max()
- Метод грубой силы (перебора)
- Функция
reduce()
- Алгоритм Heap Queue (очередь с приоритетом)
- Функция
sort()
- Функция
sorted()
- Метод хвостовой рекурсии
№1 Нахождение максимального значения с помощью функции max()
Это самый простой и понятный подход к поиску наибольшего элемента. Функция Python max()
возвращает самый большой элемент итерабельного объекта. Ее также можно использовать для поиска максимального значения между двумя или более параметрами.
В приведенном ниже примере список передается функции max в качестве аргумента.
list1 = [3, 2, 8, 5, 10, 6]
max_number = max(list1)
print("Наибольшее число:", max_number)
Наибольшее число: 10
Если элементы списка являются строками, то сначала они упорядочиваются в алфавитном порядке, а затем возвращается наибольшая строка.
list1 = ["Виктор", "Артем", "Роман"]
max_string = max(list1, key=len)
print("Самая длинная строка:", max_string)
Самая длинная строка: Виктор
№2 Поиск максимального значения перебором
Это самая простая реализация, но она немного медленнее, чем функция max()
, поскольку мы используем этот алгоритм в цикле.
В примере выше для поиска максимального значения нами была определена функция large()
. Она принимает список в качестве единственного аргумента. Для сохранения найденного значения мы используем переменную max_
, которой изначально присваивается первый элемент списка. В цикле for каждый элемент сравнивается с этой переменной. Если он больше max_
, то мы сохраняем значение этого элемента в нашей переменной. После сравнения со всеми членами списка в max_
гарантировано находится наибольший элемент.
def large(arr):
max_ = arr[0]
for ele in arr:
if ele > max_:
max_ = ele
return max_
list1 = [1,4,5,2,6]
result = large(list1)
print(result) # вернется 6
№3 Нахождение максимального значения с помощью функции reduce()
В функциональных языках reduce()
является важной и очень полезной функцией. В Python 3 функция reduce()
перенесена в отдельный модуль стандартной библиотеки под названием functools. Это решение было принято, чтобы поощрить разработчиков использовать циклы, так как они более читабельны. Рассмотрим приведенный ниже пример использования reduce()
двумя разными способами.
В этом варианте reduce()
принимает два параметра. Первый — ключевое слово max, которое означает поиск максимального числа, а второй аргумент — итерабельный объект.
from functools import reduce
list1 = [-1, 3, 7, 99, 0]
print(reduce(max, list1)) # вывод: 99
Другое решение показывает интересную конструкцию с использованием лямбда-функции. Функция reduce()
принимает в качестве аргумента лямбда-функцию, а та в свою очередь получает на вход условие и список для проверки максимального значения.
from functools import reduce
list1 = [-1, 3, 7, 99, 0]
print(reduce(lambda x, y: x if x > y else y, list1)) # -> 99
№4 Поиск максимального значения с помощью приоритетной очереди
Heapq — очень полезный модуль для реализации минимальной очереди. Если быть более точным, он предоставляет реализацию алгоритма очереди с приоритетом на основе кучи, известного как heapq. Важным свойством такой кучи является то, что ее наименьший элемент всегда будет корневым элементом. В приведенном примере мы используем функцию heapq.nlargest()
для нахождения максимального значения.
import heapq
list1 = [-1, 3, 7, 99, 0]
print(heapq.nlargest(1, list1)) # -> [99]
Приведенный выше пример импортирует модуль heapq и принимает на вход список. Функция принимает n=1
в качестве первого аргумента, так как нам нужно найти одно максимальное значение, а вторым аргументом является наш список.
№5 Нахождение максимального значения с помощью функции sort()
Этот метод использует функцию sort()
для поиска наибольшего элемента. Он принимает на вход список значений, затем сортирует его в порядке возрастания и выводит последний элемент списка. Последним элементом в списке является list[-1]
.
list1 = [10, 20, 4, 45, 99]
list1.sort()
print("Наибольшее число:", list1[-1])
Наибольшее число: 99
№6 Нахождение максимального значения с помощью функции sorted()
Этот метод использует функцию sorted()
для поиска наибольшего элемента. В качестве входных данных он принимает список значений. Затем функция sorted()
сортирует список в порядке возрастания и выводит наибольшее число.
list1=[1,4,22,41,5,2]
sorted_list = sorted(list1)
result = sorted_list[-1]
print(result) # -> 41
№7 Поиск максимального значения с помощью хвостовой рекурсии
Этот метод не очень удобен, и иногда программисты считают его бесполезным. Данное решение использует рекурсию, и поэтому его довольно сложно быстро понять. Кроме того, такая программа очень медленная и требует много памяти. Это происходит потому, что в отличие от чистых функциональных языков, Python не оптимизирован для хвостовой рекурсии, что приводит к созданию множества стековых фреймов: по одному для каждого вызова функции.
def find_max(arr, max_=None):
if max_ is None:
max_ = arr.pop()
current = arr.pop()
if current > max_:
max_ = current
if arr:
return find_max(arr, max_)
return max_
list1=[1,2,3,4,2]
result = find_max(list1)
print(result) # -> 4
Заключение
В этой статье мы научились находить максимальное значение из заданного списка с помощью нескольких встроенных функций, таких как max()
, sort()
, reduce()
, sorted()
и других алгоритмов. Мы написали свои код, чтобы попробовать метод перебора, хвостовой рекурсии и алгоритма приоритетной очереди.