Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Suppose I have a matrix M, a list

list= {{1,1}, {1,3}, {2,3}};

and a list of

values = {a,b,c}

How do I set the matrix elements {M[[1,1]], M[[1,3]], M[[2,3]]} = values?

This will produce the list elements I want:

Map[P[[Apply[Sequence, #]]] &, list] = {M[[1,1]], M[[1,3]], M[[2,3]]}

but the final command is Map, which is protected, and hence I cannot use it to set the list elements to the elements of values.

Of course one way of doing this is by looping,

For[i=1, i<=Length[list], i++, M[[Sequence @@ list[[i]] = values[[i]]]

However, since I would like to work with very large lists of indices I want to avoid loops as much as possible.

share|improve this question
    
You can directly do {M[[1, 1]], M[[1, 3]], M[[2, 3]]} = values? Or do you want it automated? – march 11 hours ago
    
Yes, I want to have it automated because I want to work with much larger lists of matrix elements. – Yiteng 11 hours ago
    
I also want to avoid loops, otherwise For[i=1, i<=Length[list], i++, M[[Sequence @@ list[[i]] = values[[i]]] would be an easy solution. – Yiteng 11 hours ago
1  
Are you modifying an existing matrix? Or are you declaring the matrix first and then putting in entries? Because if you are just making the matrix to begin with, you can do M = Normal@SparseArray[Thread[list -> values], {3, 3}]. – march 11 hours ago
    
@march Can it be done with ##? To pass list and values like in M[[1, 1]] = a. I attempted M[[##]] & /@ list = values but failed. – corey979 11 hours ago
up vote 4 down vote accepted

Given the structure that you've set up, I would probably accomplish this using MapThread. Taking

list = {{1, 1}, {1, 3}, {2, 3}};
values = {a, b, c};
m = ConstantArray[1, {3, 3}]
(* {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}} *)

do:

MapThread[(m[[Sequence @@ #1]] = #2) &, {list, values}];
m
(* {{a, 1, b}, {1, 1, c}, {1, 1, 1}} *)

Alternatively,

Scan[(m[[Sequence @@ list[[#]]]] = values[[#]]) &, Range@Length@list];

But if you are actually just creating the matrix to begin with, I would use SparseArray to construct the matrix from scratch, i.e.

Normal@SparseArray[Thread[list -> values], {3, 3}]
(* {{a, 0, b}, {0, 0, c}, {0, 0, 0}} *)
share|improve this answer
    
Thanks, this works perfectly also with a small caveat I forgot to add to the question. – Yiteng 11 hours ago
    
If I would like to keep the old values and add up the values at these indices, then MapThread[(m[[Sequence @@ #1]] += #2) &, {list, values}]; does the job, but SparseArray and ReplacePart would erase the old values. – Yiteng 11 hours ago
    
But if that was the case, then I would do something like m = m + SparseArray[Thread[list -> values], {3, 3}]. – march 11 hours ago

You can use ReplacePart and get around the difficulties with Set

m = ConstantArray[1, {3, 3}]
m = ReplacePart[m, Thread[list -> values]]
(* {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}} *)
(* {{a, 1, b}, {1, 1, c}, {1, 1, 1}} *)
share|improve this answer

for fun we can do this all with SparseArray..

m = Partition[Range[12], 3];
list = {{1, 1}, {1, 2}, {4, 3}};
values = {a, b, c};
m = SparseArray[list -> 0, Dimensions@m, 1] m + 
          SparseArray[list -> values, Dimensions@m] 

{{a, b, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, c}}

or even

m + SparseArray[list -> values - Extract[m, list], Dimensions@m]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.