11
p = {{1, 0, 0}, {0, 1, 0}, {0, 1, 0}};
p[[All, 3]][[1 ;; 2]] = {1, 1};
p

I want to replace the first two elements of the third column of a 3x3 identity matrix.

The above code does not work. I get a depth-error message.

Set::partd: Part specification is longer than depth of object

I am confused because the following code is functional.

p[[All, 3]][[1 ;; 2]]
Kuba
  • 136,707
  • 13
  • 279
  • 740
吴剑涛
  • 123
  • 6

3 Answers3

14

The way Set works in setting parts of an expression is this:

symb[[..<part specification>..]] = values;

The component symb must be a symbol (i.e. with head Symbol).

In the OP's code,

p[[All,3]][[1;;2]] = {1,1};

The symb component is p[[All,3]], which is not a symbol.

Fix as @kglr suggests,

p[[1 ;; 2, 3]] = {1, 1};

As for evaluating p[[All,3]][[1;;2]], you can see the procedure in Trace[p[[All, 3]][[1 ;; 2]]]. First p[[All, 3]] is evaluated. The expression then becomes

{0, 0, 0}[[1 ;; 2]]

(If p is meant to be the identity matrix, then the third row is wrong.)

Michael E2
  • 235,386
  • 17
  • 334
  • 747
3
p = {{1, 0, 0}, {0, 1, 0}, {0, 1, 0}};

f = MapAt[1 &, {1 ;; 2, 3}];

f @ p

{{1, 0, 1}, {0, 1, 1}, {0, 1, 0}}

If we want to change p inline we can use ApplyTo (new in 12.2)

p //= f;

p

{{1, 0, 1}, {0, 1, 1}, {0, 1, 0}}

eldo
  • 67,911
  • 5
  • 60
  • 168
1

Using SubsetMap:

p = {{1, 0, 0}, {0, 1, 0}, {0, 1, 0}};

SubsetMap[{1, 1} &, p, {{1, 3}, {2, 3}}]

({{1, 0, 1}, {0, 1, 1}, {0, 1, 0}})

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44