Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I noticed that "ReplacePart" can use pattern. For example:

ReplacePart[{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {i_, i_} -> x]
{{x, 0, 0}, {0, x, 0}, {0, 0, x}}

So I naively think I can do a little change like

ReplacePart[{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {i_+1, i_} -> x]

But it gives

{x, x, x}

Why? I anticipated that the result whould be

{{0, 0, 0}, {x,0,0}, {0, x, 0}}

Can anyone help?

share|improve this question
    
I think you may have found a bug in ReplacePart. –  m_goldberg Mar 6 '13 at 15:27
add comment

3 Answers

Use a Condition (/;) to check the relation between the values of the pattern elements. You must also use RuleDelayed (:>) instead of Rule (->), since the rule now depends on the particular values of the matched pattern.

ReplacePart[{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {i_, j_} :> 
  x /; i == j + 1]
(* {{0, 0, 0}, {x, 0, 0}, {0, x, 0}} *)

UPDATE: The erroneous-appearing result of the original code appears to be due to ReplacePart checking the second argument to see if it is a list of parts to be replaced. If the first element of the list has depth (e.g. {1} or _+1), then ReplacePart treats all elements of the list as parts to be replaced.

Consider:

(* Expected use *)
ReplacePart[Array[f, {3, 3}], {{1}, {2}, {0}} -> x]
(* x[x, x, {f[3, 1], f[3, 2], f[3, 3]}] *)

(* First element is nonsense *)
ReplacePart[Array[f, {3, 3}], {_+1, 1, 2, 0} -> x]
(* x[x, x, {f[3, 1], f[3, 2], f[3, 3]}] *)

(* First element doesn't exist *)
ReplacePart[Array[f, {3, 3}], {{7}, 1, 2, 0} -> x]
(* x[x, x, {f[3, 1], f[3, 2], f[3, 3]}] *)

SECOND EDIT: So to analyze the original case, the first element of the replacement-part list has nontrivial depth, so we treat each element as a part to be replaced. The first element is nonsense, so it matches nothing. The second element is a Blank, so it matches all integers and all parts of the list are replaced by x.

share|improve this answer
2  
can you also explain why the op got {x,x,x} in his approach? I can't make sense of that return value... –  Pinguin Dirk Mar 6 '13 at 9:41
    
+1 although I think you don't necessarily need a delayed rule here as long as you constrain the pattern appropriately: ReplacePart[{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {i_, j_} /; (i == j + 1) -> x]. –  gpap Mar 6 '13 at 12:58
    
thanks for the edits! +1 –  Pinguin Dirk Mar 6 '13 at 19:15
    
@Mr.Wizard So what about this: ReplacePart[{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, {i_, i_ + 1} -> x] gives {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}. Can I understand it as when Mathematica scan the pattern list towards i_+1, and find that it is neither a pattern nor the first element, So Mathematica just quit and do nothing?? –  matheorem Mar 7 '13 at 11:24
    
@matheorem ReplacePart examines the first item, which has trivial depth; therefore, it treats the list as a single position to be replaced. At least one element of the list is nonsense, therefore nothing is matched and nothing is replaced. –  Xerxes Mar 7 '13 at 18:21
show 3 more comments

I think a possible explanation is that when an element of the part specification passes some preliminary test but then fails to resolve to something meaningful it is removed from the list mid-process. For example:

m = Range@9 ~Partition~ 3;
r = {1, 2, 3};
x =.

ReplacePart[m, {i_ + 1, #} -> x] & /@ r // Column
ReplacePart[m, {_ + "bad", #} -> x] & /@ r // Column

Mathematica graphics
Mathematica graphics

Which is the same behavior as:

ReplacePart[m, {#} -> x] & /@ r // Column

Mathematica graphics

If the first element of the specification does not contain a pattern nothing is replaced:

ReplacePart[m, {"bad", #} -> x] & /@ r // Column

Mathematica graphics

share|improve this answer
add comment

I brought this to the attention of WRI's tech support. This is their response:

This behavior is due to the way ReplacePart processes the part position specifications given to it. When a part position specification cannot structurally match a part position, behavior of ReplacePart is technically undefined, though the proposed explanation at the MSE post to which you implicitly refer is roughly accurate. In this case, ReplacePart does end up treating each part position spec as an entire part spec due to the ambiguity of the first part position spec.

To avoid behavior like this, you can simply use Condition (/;) to enforce relationships between part position specs.

On your behalf, I've filed a suggestion with our development team to improve documentation on this aspect of ReplacePart behavior.

It nice to know that they are looking-in at what goes on here and that they accept Mr. Wizards analysis as "roughly accurate".

share|improve this answer
add comment

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.