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.

Suppose I have list

a = Range[10]

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

in which I want to set some elements to be a list

a[[4 ;; 7]] = {1, 2, 3}; 

{1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 8, 9, 10}

Which is fine and dandy unless my part span is the same length as my list:

a[[4 ;; 6]] = {1, 2, 3};

{1, 2, 3, 1, 2, 3, 7, 8, 9, 10}

How can I force the assignment to behave consistently? In my case, I always want the first behaviour. But conceivably someone might always want the second behaviour with errors if the lengths don't match.

share|improve this question

4 Answers 4

up vote 11 down vote accepted
(a[[#]] = {1, 2, 3}) & /@ Range[4, 6];

You get:

In[1]:= a

Out[1]= {1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}

A convenient thing to remember is that if your elements are not sequential it is still easy to set up:

(a[[#]] = {1, 2, 3}) & /@ {1, 3, 10};

In[2]:= a

Out[2]= {{1, 2, 3}, 2, {1, 2, 3}, 4, 5, 6, 7, 8, 9, {1, 2, 3}}
share|improve this answer
    
+1 for keeping in-place modification –  Mr.Wizard Mar 23 '12 at 0:05
2  
but this doesn't automate keeping the behaviour of Set consistent as the question asks (although it does do what is desired). then again neither does any other answer, nor anything I can come up with... –  acl Mar 23 '12 at 1:09
    
The in-place modification aspect of this answer works best for my actual problem. But as acl says, the more general question remains. –  wxffles Mar 23 '12 at 3:12

Perhaps

a = Range[10]

a[[4 ;; 6]] = Sequence@{1, 2, 3};

Returns

{1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}

However, as Mr.Wizard noted in a comment, this is a LIIIEEE. If you do Information[a] you see that the Sequence is actually being saved. I find this weird, but anyway, can be solved with an extra

a=a

Also, forcing the lhs and rhs lists to be a different size should work a[[{4,5,6,4}]]={1, 2, 3}

share|improve this answer
4  
This actually doesn't work quite seamlessly. Try Information[a]. –  Mr.Wizard Mar 22 '12 at 23:47
    
Oooooops, thanks –  Rojo Mar 22 '12 at 23:48
    
@Mr.Wizard, it's weird that essentially with Set this returns a delayed assignment. Wasn't expecting that, good catch –  Rojo Mar 22 '12 at 23:52
    
take another look. If it doesn't work, delete again. :^) –  Mr.Wizard Mar 22 '12 at 23:53
1  
+1 as this is the only answer in the spirit of the question (or anyway what I took to be the spirit of the question) –  acl Mar 23 '12 at 1:09

Here's a way that's in two-steps, but works nevertheless:

a[[4 ;; 6]] = \[FormalF][1, 2, 3];
a = a /. \[FormalF] -> List
Out[1]= {1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}

Here's another solution using MapAt, but this loses the convenience of indexing with Span.

a = MapAt[{1, 2, 3} &, a, Transpose[{Range[4, 6]}]]
Out[2]= {1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}

But the standard way to replace elements in a safe manner and for cases where you want different replacements for each, is to use ReplacePart as:

a = ReplacePart[a, Transpose[{Range[4, 6]}] -> {1, 2, 3}]
Out[3]= {1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}
share|improve this answer

After reading the answers, this is one way more to do it (maybe too simple):

a[[4 ;; 6]] = ConstantArray[{1, 2, 3}, 3];

Thinking in it, you can do your own simple Set:

Attributes[simpleSet] = {HoldFirst};
simpleSet[lhs_, rhs_] := 
  With[{newrhs = ConstantArray[rhs, Length[lhs]]}, lhs = newrhs];

And use it as Set:

simpleSet[a[[4 ;; 6]], {1, 2, 3}];
{{1, 2, 3}, {1, 2, 3}, {1, 2, 3}}

And it returns the same as Set returns: what it is assigned.

a
{1, 2, 3, {1, 2, 3}, {1, 2, 3}, {1, 2, 3}, 7, 8, 9, 10}
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.