Home > Blockchain >  Python 2D list, find corresponding first row index of a value in the array
Python 2D list, find corresponding first row index of a value in the array

Time:03-15

I am in a Python beginners class. We are not allowed to import any modules, nor use max(), min(), sort(ed)(). I have already defined my own min()max(). But for simplicity here I will use max()min(). I have a 2D array, and I am trying to find a way to reference the first line of the array, to a value in the array. Allow me to elaborate.

First row is years. First column is countries. Data in the array is population. I wrote a statement to find the max population for a country...now how do I write a statement to find which year that max population was in? Then I need to print everything out in a table, where I will have country, max population, year it happened in.

Code so far:

list = [['countries', 2019, 2020, 2025],['aruba', 2349834,23432098,8798734],['barbados', 445673,980897,342431],['japan', 12131441,7897879,3636436]]

for row in list[1:]:
        for colum in row:
            maxPop = max(row[1:])
            minPop = min(row[1:])         
            chgPop = float(f'{(((row[3] - row[1]) / row[1]) * 100):.2f}') 
        print(f'{row[0]:<10}{minPop:25}{maxPop:>20}{chgPop:>15.1f}')

This code goes to the second row, and the second column, to start working on the data for maxPop minPop and chgPop. But say now I have found a maxPop for barbados, which I can print out nicely.... how do I add another column in that print out where I print the year in which that maxPop happend?

I surmise that I would loop through the list again, and use an index reference where that maxPop happened in the list, and use the column in that index reference to pick out the year from the first row. This loop would go through the entire list, and a new variable called maxPopYear could then be added to my print statement. But how do i go about that?

The expected output would look like this

country      minpop   year   maxpop   year    pop%
aruba        1232198  2020   939439   2019    5.43
barbados     56356    2022   4544     2019    34.33
etc

CodePudding user response:

Since you need to define your max() function you can easily have it return the index of the greatest value, or even better a tuple containing both the index and the value. So when you find the maximum you also know where it is in your data. The same goes for the custom min() of course. For instance you may do:

def mymax(it):
    maxval = -1
    for i,v in enumerate(it):
        if v > maxval:
            maxval = v
            maxidx = i
    return (maxidx, maxval)

mymax([445673,980897,342431])
(1, 980897)

CodePudding user response:

So you can use the built in function for list in python called index.

data = [
    ["countries", 2019, 2020, 2025],
    ["aruba", 2349834, 23432098, 8798734],
    ["barbados", 445673, 980897, 342431],
    ["japan", 12131441, 7897879, 3636436],
]

for row in data[1:]:
    for column in row:
        maxPop = max(row[1:])
        minPop = min(row[1:])
        chgPop = float(f"{(((row[3] - row[1]) / row[1]) * 100):.2f}")
        year = data[0][row.index(maxPop)]
    print(f"{row[0]:<10}{minPop:25}{maxPop:>20}{chgPop:>15.1f}{year:>20}")

This outputs:

aruba                       2349834            23432098          274.4                2020
barbados                     342431              980897          -23.2                2020
japan                       3636436            12131441          -70.0                2019

the easy implementation of the index function is

def index(a:list, value) -> int:
    for i, item in enumerate(a):
        if item == value:
            return i
    raise ValueError(f"{value} not in list")

To use it just replace the line with year = data[0][index(row, maxPop)]

Or even better, just like @gimix suggested, return the index along as a tuple with your max or min function. You can have a function called argmin and argmax which returns only the index of the min and max values respectively and use that to get the value.

def argmax(it:list) -> int:
    maxval = -1
    maxidx = None
    for i, v in enumerate(it):
        if v > maxval:
            maxval = v
            maxidx = i
    return maxidx
  • Related