-1

I'm trying to find the right max value from below dp. as you can see, the max value is 3.

dp = [[0, 0, 0, 1], [1, 1, 0, 1], [1, 2, 1, 1], [0, 1, 2, 2], [0, 1, 2, 3]]

When using max(max(dp)), i got 2, which is wrong. But why?

max(dp) gives me [1,2,1,1]. If the max is taken along the y axis, shouldn't max(dp) return [1,2,2,3]?? when using max([max(x) for x in dp]), i got 3, which is correct

azro
  • 53,056
  • 7
  • 34
  • 70
Lisa
  • 4,126
  • 12
  • 42
  • 71
  • `max((max(d) for d in dp))`? – not_speshal Jun 22 '21 at 18:58
  • It is strongly advised to use `numpy` for numerical operations on arrays. Don't use Python lists (or lists of lists, etc.). You'll get burned every time by weird and not-well-documented behavior. – Alex Reynolds Jun 22 '21 at 19:01
  • It is really important to understand, *list objects don't have dimensions/axes*. List objects are sequences of other objects. When you do `max(dp)` it returns the largest object in your list, which is the list, `[1, 2, 1, 1]`. Anyway, you seem to already have you right answer. Here's a more succinct way: `max(map(max, dp))` but what you have is fine – juanpa.arrivillaga Jun 22 '21 at 19:02
  • @AlexReynolds absolute nonsense. List objects don't have any weird or undocumented behavior in particular, certainly not over `numpy`, and they are perfectly acceptable for many use-cases. Certainly, there is nothing weird or undocumented about the behavior the OP is discussing. – juanpa.arrivillaga Jun 22 '21 at 19:03

3 Answers3

3

Classic python knows only one dimension, if you pass values to a comparative method, then it'll compare them, it won't go further

The right way is max((max(x) for x in dp)) as you said (just used a generator instead of a list inside)

Using numpy you can handle multiple dimensions

import numpy as np
x = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]
print(np.max(np.array(x)))  # 12

For max(dp) you look for the max of the following values, which will be computed by looking each element index by index, the maximum at index 0 is 1, but you have 2 possiblities, so you go one index further and the max of that second index is 2 and you have the winner

[0, 0, 0, 1], 
[1, 1, 0, 1], 
[1, 2, 1, 1],  <<<
[0, 1, 2, 2], 
[0, 1, 2, 3]

As max(dp) == [1, 2, 1, 1] then max(max(dp)) == max([1, 2, 1, 1]) which is 2

azro
  • 53,056
  • 7
  • 34
  • 70
2

The problem is python has no notion of multi-dimensional arrays built in.

When you call max on a list of lists, you end up with a list that is highest in the lexicographic order, not the one containing the highest element.

x = [ [4,2,3], [3,10,0] ]
max(x) == [4,2,3] # does not contain 10
max(max(x)) == 4 

In other words max(max(x)) in python is not the highest value over two axes of x, but rather the maximal value in an entry of x, that is highest under the default ordering of the objects there (which for lists is lexicographic).

The easiest way is to use numpy, which has a proper way of interpreting k-dimensional arrays

import numpy as np
np.max(x) == 10 # as expected
lejlot
  • 64,777
  • 8
  • 131
  • 164
-1
def largestNumber(list):
    result = []
    for i in range(0, len(list)):
        largestNumber = list[i][0]
        for j in range(0, len(list[i])):
            if list[i][j] > largestNumber:
                largestNumber = list[i][j]
        result.append(largestNumber)
    return max(result)


print(largestNumber([[0, 0, 0, 1], [1, 1, 0, 1],
      [1, 2, 1, 1], [0, 1, 2, 2], [0, 1, 2, 3]]))

Code Explanation:

  1. Create a variable to store the results as an array.

  2. Create an outer loop to iterate through the outer array.

  3. Create a second variable to hold the largest number and initialize it with the first number. This must be outside an inner loop, so it won’t be reassigned until we find a larger number.

  4. Create said inner loop to work with the sub-arrays.

  5. Check if the element of the sub-array is larger than the currently stored largest number. If so, then update the number in the variable.

  6. After the inner loop, save the largest number in the corresponding position inside the results array.

  7. And finally, return the said array.

Thanks to @juanpa.arrivillaga for helping me make my code more precise. Both code snippets have similar code explanation:

def largestNumber(list):
    result = []
    for item in list:
        largestNumber = item[0]
        for j in item:
            if j > largestNumber:
                largestNumber = j
        result.append(largestNumber)
    return max(result)


print(largestNumber([[0, 0, 0, 1], [1, 1, 0, 1],
      [1, 2, 1, 1], [0, 1, 2, 2], [0, 1, 2, 3]]))

The second method employs a different method of using a for loop, which is concise than the for loop that has range() in it. It gets the job done in a relatively more pythonic way.

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • why is this preferable to the op's `max([max(x) for x in dp])`??? It's the exact same algorith, just that you are iterating unidiomatically. Don't use `for i in range(...)` And if you are going to iterate over everything, why keep a list of intermediate largest numbers, just to use `max` on that list at the end? why not just keep the largest number? – juanpa.arrivillaga Jun 22 '21 at 19:14
  • @juanpa.arrivillaga I just prefer solving an algorithmic problem in detail, and I prefer doing everything manually with the least amount of built-in functions employed. – Harris Ahmad Jun 22 '21 at 19:16
  • 1
    Then why use `for i in range(0, len(list))`? That's *two* built-in functions, instead of `for sublist in list:`... (don't use `list` as a variable name) and anyway, you *end up using `max` anyway* – juanpa.arrivillaga Jun 22 '21 at 19:17
  • @juanpa.arrivillaga You're right! Thanks for the suggestion! I'll definitely take it into account. The for loop that I have used makes my code convoluted. – Harris Ahmad Jun 22 '21 at 19:20