17
$\begingroup$

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.

$\endgroup$

4 Answers 4

11
$\begingroup$
(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}}
$\endgroup$
2
  • 2
    $\begingroup$ 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... $\endgroup$
    – acl
    Commented Mar 23, 2012 at 1:09
  • $\begingroup$ The in-place modification aspect of this answer works best for my actual problem. But as acl says, the more general question remains. $\endgroup$
    – wxffles
    Commented Mar 23, 2012 at 3:12
11
$\begingroup$

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}

$\endgroup$
7
  • 4
    $\begingroup$ This actually doesn't work quite seamlessly. Try Information[a]. $\endgroup$
    – Mr.Wizard
    Commented Mar 22, 2012 at 23:47
  • $\begingroup$ Oooooops, thanks $\endgroup$
    – Rojo
    Commented Mar 22, 2012 at 23:48
  • $\begingroup$ @Mr.Wizard, it's weird that essentially with Set this returns a delayed assignment. Wasn't expecting that, good catch $\endgroup$
    – Rojo
    Commented Mar 22, 2012 at 23:52
  • $\begingroup$ take another look. If it doesn't work, delete again. :^) $\endgroup$
    – Mr.Wizard
    Commented Mar 22, 2012 at 23:53
  • 1
    $\begingroup$ +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) $\endgroup$
    – acl
    Commented Mar 23, 2012 at 1:09
7
$\begingroup$

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}
$\endgroup$
0
5
$\begingroup$

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}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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