2
votes

How to set the same value to the matrix of multiple rows and each row with different column numbers without for loop? For example for matrix a:

a=matrix([[1,2,3],
          [8,2,9],
          [1,8,7]])

row = [1,2,3]
col = [[1,2]
       [1,3]
       [2,3]]  

I want to set a[1,1],a[1,2],a[2,1],a[2,3],a[3,2],a[3,3] to the same value. I know use for loop:

for i in xrange(len(row)):
    a[row[i],col[i]] = setvalue    

But is there anyway to do this without for loop?

3
"Without loop". Do you mean without a loop in python, without a loop in the use of the code, something else? There will need to be a loop somewhere, even if it's deep in the guts of the interpreter, like with the list initializer syntax. I'm envisioning a custom python class matrix that you could make with the method matrix.setValue(rows, cols, value). This would require a loop internally to the matrix class, but not in how you use the method.Frank Bryce
@AmiTavory a is just a matrix, whose entries can be int or float.Matthew
@JohnCarpenter Thank you! Yes, I mean a loop in the python code. I think the loop deep in the interpreter should be faster than loop used in the code.Matthew

3 Answers

2
votes

Using numpy, you can avoid loops:

import numpy as np
from numpy.matlib import repmat

a = np.array([[1,2,3],
              [8,2,9],
              [1,8,7]])

row = np.array([[1],
                [2],
                [3]])

col = np.array([[1,2],
                [1,3],
                [2,3]])

row = repmat(row,1,col.shape[1])

setvalue = 0
a[row.ravel(),col.ravel()] = setvalue

However, it's important to note that in python indexing starts at 0, so you should actually do

a[row-1,col-1] = setvalue

Or even better, use the correct (zero-based) indices to initialise your row and col arrays.

0
votes

Case 1: Use list comprehension

You can do like this:

value = 2
col_length = 3
line_length = 3
a = [[value for x in range(col_length)] for x in range(line_length)]

If you print a,

[[2, 2, 2], [2, 2, 2], [2, 2, 2]]

EDIT: Case 2 : Use map()

I am not very used to this one. But you can find more informations about it here in terms of performance. General idea: it seems faster when used with one function and no lambda expression.

-1
votes

You'll have to use a for loop.

Usually you want to avoid for loops (by using comprehesions) when following the functional paradigm, by building new instances instead of mutating the old one. As your goal is to mutate the old one, somewhere you will need a loop. The best you can do is to wrap it up in a function:

def set_items_to(mx, indices, value=0):
  for row,cols in indices:
    for col in cols:
      mx[row, col] = value

a = matrix([[1,2,3],[4,5,6],[7,8,9]])
set_items_to(a, [
  [0, [0,1]],
  [1, [0,2]],
  [2, [1,2]]
], setvalue)

EDIT

In case it is a programming challenge, there are ways to accomplish that without explicit for loops by using one of the built in aggregator functions. But this approach doesn't make the code clearer nor shorter. Just for completeness, it would look something like this:

def set_items_to(mx, indices, value=0):
  sum(map(lambda item: [0,
    sum(map(lambda col: [0,
      mx.__setitem__((item[0], col), value)
    ][0], item[1]))
  ][0], indices))