r/learnpython • • Aug 02 '24

What's wrong with the max module of python ?

The answer of this code is wrong. The output is supposed to be 25 but for some reason it's 9.

Code:

list=['9', '12', '8', '25', '23']

biggest_number=max(list)

print(biggest_number)

I tried the following code with the following input in different IDE's but every single one of them gave the same answer, maybe the max module is taking the 9 as 90. Any comments or help would be appreciated to solve this issue.

0 Upvotes

51 comments sorted by

22

u/[deleted] Aug 02 '24 edited Aug 02 '24

Run this code to see the problem in action:

print(f"{'9' < '25'=}")   # compare strings
print(f"{ 9  <  25 =}")   # compare integers

0

u/Important_Rip6864 Aug 02 '24

so, In my case the numbers are a string and the max module is considering the hexadecimal values of the numbers to determine the biggest number ?

if that's so, then how do i solve this issue ?

39

u/ConfusedSimon Aug 02 '24

Not hexadecimal, just alphabetical. '9' comes after '25' just like 'z' comes after 'az'.

5

u/jeffcgroves Aug 02 '24

"Hexadecimal value" is an odd turn of phrase, but I'd say alphabetically. Remember "1" comes before "9" in the alphabet, so "10" comes before "9". Unix programs like sort deal with this via options (-n is numeric sort)

To fix, just remove the quotation marks so Python treats your numbers as numbers

1

u/bhonbeg Aug 04 '24

sort -V for the win! Version sort applicable not just w version numbers

1

u/[deleted] Aug 03 '24 edited Aug 03 '24

You have some answers, but just perhaps to clarify a little....

the max module is considering the hexadecimal values of the numbers

Not the numeric value of the whole string. The max() function compares the value of elements in the sequence it is given. When the elements are strings the comparison starts with the first character of each string. If one of those two characters is larger in numeric value than the other that is the "larger" string. If the two characters have the same value then the next two characters are compared, and so on. This continues until either one character is larger, or both strings finish at the same position, meaning the strings are equal.

The "value" of a character is the numeric value you get if you do ord() on the character. This code shows some values of characters. Note that the value for "a" is less than the value for "b":

for char in "abcd":
    print("char =", char, ", ord(char) =", ord(char))

how do i solve this issue

If you want numeric strings to be sorted numerically, you have to convert the strings to numbers first before using max(). For integer strings you can use the int() function:

integer = int("1234")

10

u/[deleted] Aug 02 '24

[removed] — view removed comment

14

u/mcs5280 Aug 02 '24

Or convert when passing to max if list truly needs to contain strings :

biggest number = max([int(x) for x in list])

6

u/angelicosphosphoros Aug 02 '24

Actually, it is possible to write like this: max(int(x) for x in list)

This will not create intermediate list.

1

u/Spiderfffun Aug 02 '24

Could you use the map function here?

1

u/mcs5280 Aug 03 '24

I believe that would work too. One of the other posters has a more efficient solution (skip square brackets) that doesn't make an intermediate list so I would recommend that

-59

u/Important_Rip6864 Aug 02 '24

i didn't even knew you can do that, how am I supposed to beat the AI programmers

28

u/chason Aug 02 '24

This has nothing to do with AI programmers?

23

u/oclafloptson Aug 02 '24

From what I've seen of AI code you're on par actually lol

4

u/ivosaurus Aug 02 '24

There are 10,000 things one doesn't know as a new programmer. That's no reason not to start on your journey, or to randomly stop somewhere in the middle.

2

u/liltbrockie Aug 02 '24

You are trying to beat AI programmers?

2

u/unixtreme Aug 02 '24

This is a very standard pattern. Just keep at it and don't get distracted with that stuff.

2

u/szayl Aug 02 '24

lolwut

-2

u/Important_Rip6864 Aug 02 '24

originally I faced this problem, when i tried to use the 'split' function to turn a string of numbers separated by space into a list, but whenever i use the split function, there are the quotation marks. Any idea on how i can solve it ?

here is the code for reference:

string_of_numbers= input('Enter your string of numbers')
list_of_The_string=string_of_numbers.split()
biggestNumber=max(list_of_The_string)
print(list_of_The_string)
print(biggestNumber)

7

u/AniX72 Aug 02 '24

That's because split() will return a list of string values, while it seems you want to max() to treat them like numbers. You can convert a string to an integer with int() (given they consist of numbers, not letters etc.). For example:

string_of_numbers= input('Enter your string of numbers')
list_of_The_string=string_of_numbers.split()
list_of_numbers=[int(value) for value in list_of_The_string])
biggestNumber=max(list_of_numbers)
print(list_of_The_string)
print(biggestNumber)

This will produce a list of integer values and pass it to max().

3

u/Ghostexist90 Aug 02 '24

Sure split() will return a list of string values, since it's one of the python string methods... The correct hint would be, that input() will always initially be a string. It even says it in his code "Enter your string of numbers".

But everything else is correct.

131

u/danielroseman Aug 02 '24

These are strings. Strings are always compared lexicographically. 

If you want to compare numerically, use numbers, ie ints.

3

u/whitelife123 Aug 03 '24

Funnily enough in JavaScript, ints are still compared lexicographically. You have to pass a lambda to get them to compare numerically

1

u/JohnnyJordaan Aug 03 '24

Not just 'in JavaScript' in general, as the < and > work just as you would expect, numerically. It's that many sequence methods, like Array.sort, work exclusively lexicographically (as from JS principles, dynamic behavior based on the type makes less sense). But when talking a max() equivalent, you would rather use Math.max() and that works, as the name suggests, numerically too.

1

u/whitelife123 Aug 04 '24

Ah, thanks for the clarification, it's been a while since I've done data wrangling in JS. Learned this tidbit when I was working on a dataviz project

93

u/cyberjellyfish Aug 02 '24

You've gotten good answers, but I'm going to give you some advice that will serve you well:

Everyone occasionally gets to a point where they think something in the standard library or a ubiquitously used library is obviously broken.

It's not broken. You're the problem. Go back and validate your assumptions. Take a break and come back. 99.99999% of the time you'll find a simple mistake in your own code.

This happens to and the advice applies to every developer, at every experience level.

24

u/Skirlaxx Aug 02 '24

That's a good advice. Though I think op knows it and just didn't want to accept it. It's like when at 1:30 am, I still try to blame my model errors on pytorch, because I refuse to accept I made a mistake somewhere and probably shouldn't be coding at 1:30 am to begin with, since I can barely remember what file I am in and what it is I am trying to do.

4

u/twist3dlogic Aug 02 '24

I've been here too many times..

6

u/CraigAT Aug 02 '24

I too have a little chuckle when I see posts like this one. Partly because I have been there myself, you have been struggling with an issue for so long and have tried all sorts of things, but it just doesn't appear to be doing what you think it should.

It's natural that when you have exhausted all other possibilities, the one that remains has to be the solution.

But in almost all cases regarding the Python standard libraries, they are not wrong. Their code and outcomes have been tested billions of times by both users and programmatically by unit tests etc.

I think alongside errors in your code, probably just as many issues are down to not truly understanding the implementation of the function they are using - often the developer made sane decisions for cases you never thought of, which means it may not work how you expect it to.

1

u/ryoko227 Aug 02 '24

Absolutely this. I'm a learner, and I cannot count how many times I have written something that "I knew was right," only to have it be some silly mistake I had made.

This actually happened this morning in VSC. My indents were getting an extra space after writing if or for loops. Seems somewhere further up in the code I had indented something that was not error generating, but enough for VSC to behave unexpectedly.

-1

u/bot_exe Aug 03 '24

Also he could have just asked any LLM and gotten a simple explanation instantly. Testing on multiple IDEs and even making this thread was a waste of time.

26

u/JohnnyJordaan Aug 02 '24

The answer of this code is wrong

The answer is correct

What's wrong with the max module of python

It's a function and there's nothing wrong with it.

Please consider the origin of the problem to be between your keyboard and your chair, not with a programming language maintained and further expanded by hundreds of developers. Just because you don't immediately understand why max() sorts strings differently than ints, means you need to understand why it works that way.

6

u/[deleted] Aug 02 '24

Thank you. The tendency of beginners to assume the machine is somehow doing something wrong is absolutely beyond my understanding. Smells of insane levels of hubris.

15

u/[deleted] Aug 02 '24

You have your answer so I will address this title.

What's wrong with the max module of python ?

Get out of this habit immediately. It is overwhelmingly unlikely that you have discovered a real problem with the builtin library code. You should get into the mindset of "what am I missing", not "why is the language wrong", because it will be the former 99.99999% of the time. Especially as a beginner, the idea that the module is somehow wrong sounds like an unbelievable level of hubris.

The language is basically never wrong. It literally always does exactly what you tell it.

1

u/bhonbeg Aug 04 '24

Lol your answer is like coincidentally and not AI-identally the same as cyberjellyfish except they provided the 99.999999 with 6 nines after the decimal point. We are all fucking clones!

6

u/UsernameTaken1701 Aug 02 '24

Try print(sorted(listNums)) and see what you get.

Now try print(sorted([int(i) for i in listNums])) . Your list items have to be made into integers to work with max() the way you want..

Also, don't use list as a variable name. It's a data type, and also a function list() that can make lists from iterable objects like strings. It's weird it's not a reserved word.

2

u/__nickerbocker__ Aug 02 '24

Emphasizing: never use built-in symbols as variable names. You will do it and you will spend a good amount of time debugging and you will remember this advice. Also, you can simply pass int for a bit cleaner version:

sorted_list = sorted(str_nums, key=int)

2

u/UsernameTaken1701 Aug 03 '24

Oh, yeah, that is a much nicer approach--don't even have to convert it to int Don't even need a new list if you just drop it in as print(sorted(str_nums, key=int)). Thanks, TIL.

4

u/Binary101010 Aug 02 '24

The answer of this code is wrong.

Strings are sorted lexicographically, and what that means for strings starting with digits is that all of the first digits are compared: "8" is greater than "7" etc. If there's a tie on the first digit then the second digits of those involved in the tie are compared, and so on.

As the list you provided to max() consisted only of strings, it returned the correct answer for that list.

If your intent was to have these items compared in the way you'd expect integers to be compared, then you need to pass it a list of integers.

list = [9,12,8,25,23]

4

u/SisyphusAndMyBoulder Aug 02 '24

What's wrong with the max module of python ?

Word of advice? If you're using a built-in function or importing something and it's not working as expected, chances are you're doing something wrong & the function is working exactly as it should be.

I find it much easier to debug when I assume I did something wrong instead of assuming a core library is misbehaving.

3

u/Altrooke Aug 02 '24

And THANK GOD python works likes this. I can only imagine what a mess it would be if python tried to infer the types based on string content.

3

u/[deleted] Aug 02 '24

Nothing is wrong with it, you're just not comparing numbers.

Which is greater? "Dictionary" or "abracadabra"?

1

u/tm80401 Aug 02 '24

Because you are putting characters in your list, not numbers.  It's correct.

1

u/CrusaderGOT Aug 02 '24

First convert your list of strings to list of ints, like, int_list = [int(num) for num in list] Then perform your operation. But this isn't the optimal way.

First don't name your variables the same as any python globals, in your case list should be something like str_list .

Also just save the elements in your list as ints to avoid all this, you can use the int() function to convert them from their incoming source if any. Using a list comprehension to convert them becomes difficult if the elements in your list are super plenty.

1

u/Rinzwind Aug 02 '24

to convert a list of strings into integers

[int(x) for x in list]
[int(x) for x in list]

1

u/mattynmax Aug 02 '24

You’re giving it strings not numbers….

1

u/BalStrate Aug 02 '24

They're considered as strings Comparison in strings are done on the first character, and in case they're equal, it goes to the second character and so on

In fact '9'>'12' since '9'>'1'

1

u/six4one Aug 03 '24

Another mistake you've made that doesn't affect your code now, but later on, you'll find yourself getting weird bugs, naming the list "list". You should give it a different name that's not a Python keyword, function, or module name that you've imported. Otherwise, if you try to convert something to a list, eg

list("1234")

Expected output:

["1", "2", "3", "4"]

Instead, you will get the following error:

TypeError: "list" object is not callable

0

u/xrsly Aug 02 '24 edited Aug 02 '24

input() will always return a string, so if you expect the input to be a list of integers, then you have to validate and convert each "number" to an int. Perhaps like this:

numbers_as_string = input("Please enter a series of numbers (e.g.: 1, 2, 3): ") 

try:
    numbers = [int(num) for num in string_of_numbers.split()]
except ValueError:
    raise ValueError(f"Some numbers were not valid: {[i for i in numbers_as_strings.split() if i.isdigit() is False]}"}

NOTE: There are many ways to solve this, this is just an example.

Breakdown of the code:

  1. First we take the input from the user (remember that this will always be a string no matter what)

  2. Then we use the try/except statement, which basically just means that we are going to try to do something, and if a certain error occurs, then we can "catch" it and write our own error message for it. If we try to convert a non-number to an int, then a ValueError occurs, so we write "except ValueError:" to catch that specific error.

  3. In this case, we will try to convert each "word" in the string to a number, so that e.g., "42" becomes 42. Note that split() will take any string and return a list of words (space will be used as a separator by default, so "hello 42" becomes ["hello", "42"], whereas "hello_42" becomes ["hello_42"], since there is no space. Now, if the user enters something that's not a number, then the error message will tell them that some "words" were not valid numbers. So "hello 42" would result in the error: "ValueError: Some numbers were not valid: ["hello"]. You can write whatever error message you want of course.

  4. If the user entered only valid numbers, then the result will be e.g., "42 21 11" -> [42, 21, 11]

  5. Now you have a list of integers, so you can use max(numbers) to find the biggest one.