Hussam Gold
Hussam Gold

Reputation: 13

calculating the average of nested array in particular manner by python?

i need a way to calculate the average of the nested array ( even or odd ) in this following manner:

let's say we have this array ( list ) ( even 4*4 ) :

mylist = [
[1,6,5,6],
[2,5,6,8],
[7,2,8,1],
[4,4,7,3]
] 

the output must be like this

mylist = [[3,6],
[4,4]
]

based on this calculation

1 + 6 + 2 + 5 / 4 = 3
5 + 6 + 6 + 8 / 4 = 6
7 + 2 + 4 + 4 / 4 = 4
8 + 1 + 7 + 3 / 4 = 4

the same thing if we have an odd nested array like this

mylist = [[7,9,1],
[4,2,1],
[3,2,3]]

the output would be :

mylist = [[5,1],
[2,3]
]

based in same calculation above ..

7 + 9 + 4 + 2 / 4 = 5
1 + 1 / 2 = 1
3 + 2 / 2 = 2
3 / 1 = 3

so how we can implement this process by python, notice that i know how to do the normal average for each array like just increasing the numbers for each array line by line and divided by its count ..

 mylist = [[70,80,90],
[30,40,50],
[0,10,20],
[10,40,40]]
avglist = []
for x in mylist:
    temp = 0
    counter = 0
    for y in x:     
        temp = temp + y
        counter = counter + 1
    avglist.append(temp/counter)
    print()
print()
print(avglist)

but in that problem .. i face a problem to how to jump to next array then came back to first array and so forth ....

**

notice: it has to be a square array ( row length = column length )

**

Upvotes: 1

Views: 985

Answers (3)

Cireo
Cireo

Reputation: 4427

A bit golfy, sorry, typing on phone means short names :). I take advantage of integer division to simply the logic, and use totals plus division over intermediate lists.

from itertools import product

def quad_avgs(M):
  sums = [[0,0],[0,0]]
  L, S, s = len(M), len(M) / 2, len(M) - len(M) / 2
  for r, c in product(range(L), repeat=2):
      sums[r / S][c / S] += M[r][c]
  return [[sums[r][c] / ([S, s][r] * [S, s][c]) for c in [0, 1]] for r in [0, 1]]

Upvotes: 1

Jethro Cao
Jethro Cao

Reputation: 1050

Okay so here's my try. It's a bit verbose, but I think it's very easy to follow.

# helper func to split nested list (NxN matrix) into 4 quadrants
def split_mat(mat):
    n = len(mat)
    s = math.ceil(n/2)
    up_left  = [mat[i][j] for i in range(0, s) for j in range(0, s)]
    up_right = [mat[i][j] for i in range(0, s) for j in range(s, n)]
    bt_left  = [mat[i][j] for i in range(s, n) for j in range(0, s)]
    bt_right = [mat[i][j] for i in range(s, n) for j in range(s, n)]
    return [up_left, up_right, bt_left, bt_right]

# then the averages you want to calculate becomes trivial
def avg_mat(mat):  
    quadrants = split_mat(mat)
    avgs = [sum(q)//len(q) for q in quadrants]
    return [[avgs[0], avgs[1]], [avgs[2], avgs[3]]]
even_list = [
[1,6,5,6],
[2,5,6,8],
[7,2,8,1],
[4,4,7,3]]

print(avg_mat(even_list))
--------------------------------------------------
[[3, 6], [4, 4]]
odd_list = [
[7,9,1],
[4,2,1],
[3,2,3]]

print(avg_mat(odd_list))
--------------------------------------------------
[[5, 1], [2, 3]]

Upvotes: 1

Green Cloak Guy
Green Cloak Guy

Reputation: 24691

I present a frame challenge: instead of counting each quadrant one at a time, count all quadrants at once.

Assuming we are always computing four numbers (the sums of each quadrant, with a bias towards the top-left quadrant if the sizes are unequal), we can simply prepare them in advance, and then scan over each cell of the matrix, determine which quadrant it's in, and increment that sum:

def calculation(matrix):
    # prepare empty lists for each quadrant
    # we will add each element from the matrix to the list that corresponds to its quadrant
    # then at the end we will take the average of each.
    sums = {
        (True, True):   [],  # top-left
        (True, False):  [],  # top-right
        (False, True):  [],  # bottom-left
        (False, False): [],  # bottom-right
    }
    # scan over each cell by row and column index
    for row in range(len(matrix)):
        for col in range(len(matrix[row])):
            # use boolean checks to index into sums depending on quadrant
            sums[(row < len(matrix) / 2,      # is it in the top half?
                  col < len(matrix[row]) / 2  # is it in the left half?
                )].append(matrix[row][col])
    # calculate and return averages (using integer division instead of true division)
    return [[sum(sums[True, True])   // len(sums[True, True]),     # top-left
             sum(sums[True, False])  // len(sums[True, False])],   # top-right
            [sum(sums[False, True])  // len(sums[False, True]),    # bottom-left
             sum(sums[False, False]) // len(sums[False, False])]]  # bottom-right

Test cases:

>>> mylist = [
... [1,6,5,6],
... [2,5,6,8],
... [7,2,8,1],
... [4,4,7,3]
... ] 
>>> calculation(mylist)
[[3, 6], [4, 4]]

>>> mylist = [[7,9,1],
... [4,2,1],
... [3,2,3]]
>>> calculation(mylist)
[[5, 1], [2, 3]]

Upvotes: 0

Related Questions