Home > Net >  compare each row with each column in matrix using only pure python
compare each row with each column in matrix using only pure python

Time:09-14

I have a certain function that I made and I want to run it on each column and each row of a matrix, to check if there are rows and columns that produce the same output.

for example:

matrix = [[1,2,3],
          [7,8,9]]

I want to run the function, lets call it myfun, on each column [1,7], [2,8] and [3,9] separatly, and also run it on each row [1,2,3] and [7,8,9]. If there is a row and a column that produce the same result, the counter ct would go up 1. All of this is found in another function, called count_good, which basically counts rows and columns that produce the same result.

here is the code so far:

def count_good(mat):
    ct = 0
    for i in mat:
        for j in mat:
            if myfun(i) == myfun(j):
                ct  = 1
    return ct
            

However, when I use print to check my code I get this:

mat = [[1,2,3],[7,8,9]]
​
for i in mat:
    for j in mat:
        print(i,j)
​
[1, 2, 3] [1, 2, 3]
[1, 2, 3] [7, 8, 9]
[7, 8, 9] [1, 2, 3]
[7, 8, 9] [7, 8, 9]

I see that the code does not return what I need' which means that the count_good function won't work. How can I run a function on each row and each column? I need to do it without any help of outside libraries, no map,zip or stuff like that, only very pure python.

CodePudding user response:

Let's start by using itertools and collections for this, then translate it back to "pure" python.

from itertools import product, starmap, chain # combinations?
from collections import Counter

To iterate in a nested loop efficiently, you can use itertools.product. You can use starmap to expand the arguments of a function as well. Here is a generator of the values of myfun over the rows:

starmap(myfun, product(matrix, repeat=2))

To transpose the matrix and iterate over the columns, use the zip(* idiom:

starmap(myfun, product(zip(*matrix), repeat=2))

You can use collections.Counter to map all the repeats for each possible return value:

Counter(starmap(myfun, chain(product(matrix, repeat=2), product(zip(*matrix), repeat=2))))

If you want to avoid running myfun on the same elements, replace product(..., repeat=2) with combinations(..., 2).

Now that you have the layout of how to do this, replace all the external library stuff with equivalent builtins:

counter = {}
for i in range(len(matrix)):
    for j in range(len(matrix)):
        result = myfun(matrix[i], matrix[j])
        counter[result] = counter.get(result, 0)   1
for i in range(len(matrix[0])):
    for j in range(len(matrix[0])):
        c1 = [matrix[row][i] for row in range(len(matrix))]
        c2 = [matrix[row][j] for row in range(len(matrix))]
        result = myfun(c1, c2)
        counter[result] = counter.get(result, 0)   1

If you want combinations instead, replace the loop pairs with

for i in range(len(...) - 1):
    for j in range(i   1, len(...)):

CodePudding user response:

Using native python:

def count_good(mat):
    ct = 0
    for row in mat:
        for col_idx in range(len(mat[0])):
            column = [x[col_idx] for x in mat]
            if myfun(row) == myfun(column):
                ct  = 1
    return ct

However, this is very inefficient as it is a triple nested for-loop. I would suggest using numpy instead.

e.g.

def count_good(mat):
    ct = 0
    mat = np.array(mat)
    for row in mat:
        for column in mat.T:
            if myfun(row) == myfun(column):
                ct  = 1
    return ct
  • Related