Re: Q: efficient in-place list element replacement?

• To: mathgroup at smc.vnet.net
• Subject: [mg21159] Re: [mg21091] Q: efficient in-place list element replacement?
• From: Andrzej Kozlowski <andrzej at tuins.ac.jp>
• Date: Fri, 17 Dec 1999 01:22:32 -0500 (EST)
• Sender: owner-wri-mathgroup at wolfram.com

```My cautious anser to your questions is: its almost certainly a bug. Still, I
have checked that it has been around at least since version 2, and it maybe
difficult to fix it without sacrificing some speed.
It seems that when you use Sequence in your way it does not quite vanish for
all purposes, although indeed it becomes invisible to FullForm etc. It will
vanish once Mathematica is forced to reconstruct the list, e.g.:

In[1]:=
a = {4, 5, 6, 7, 67, 89}
Out[1]=
{4, 5, 6, 7, 67, 89}
In[2]:=
p = 3;
In[3]:=
a[[p]] = Sequence @@ {"a", "b", "c"};
In[4]:=
a = a - Table[0, {Length[a]}]
Out[4]=
{4, 5, "a", "b", "c", 7, 67, 89}
In[5]:=
a[[7]] = Pi
Out[5]=
\[Pi]
In[6]:=
a
Out[6]=
{4, 5, "a", "b", "c", 7, \[Pi], 89}

So everything works fine  but there is a price to be paid in speed.

Another possible way round is to use ReplacePart instead of Set and Part.
The folowing works without any apparent glich:

In[1]:=
a = {4, 5, 6, 7, 67, 89}
Out[1]=
{4, 5, 6, 7, 67, 89}
In[2]:=
p = 3;
In[3]:=
a = ReplacePart[a, Unevaluated[Sequence["a", "b", "c"]], p]
Out[3]=
{4, 5, "a", "b", "c", 7, 67, 89}
In[4]:=
a[[7]] = Pi
Out[4]=
\[Pi]
In[5]:=
a
Out[5]=
{4, 5, "a", "b", "c", 7, \[Pi], 89}

(I have not tired checking how using Part and Set compres with ReplacePart
in terms of speed so I am not sure if using the latter is really an answer
--

> From: simon shannon <sshannon at taz.dra.hmg.gb>
To: mathgroup at smc.vnet.net
> Organization: dera
> Date: Sun, 12 Dec 1999 23:51:59 -0500 (EST)
> To: mathgroup at smc.vnet.net
> Subject: [mg21159] [mg21091] Q: efficient in-place list element replacement?
>
> dear Mathematica wizards,
>
> how can i do efficient in-place list element replacement?
> i have a small nugget of 'unexpected behaviour' that took me
> hours to track down. vastly simplified, the problem is this:
>
> a = {4,5,6,7,67,89}
>
> i know i want to replace the third element with
> some new elements:
>
> p = 3;
>
> a[[p]] = Sequence @@ {"a","b","c"};
>
> i look at the result, and a is apparently
>
> {4, 5, a, b, c, 7, 67, 89}
>
> Length[a] returns 8; still looks good...
> a[[4]] returns "b"; still looks good...
>
> now we change the 7th element of our list
>
> a[[7]] = Pi;
>
> ....and we get the blue error message
>
> Set::partw: Part 7 of {4, 5, Sequence[a, b, c], 7, 67, 89} does not
> exist.
>
>
> so, my first questions are:
>
> (1) why is the Sequence head still there?
> (2) why was it invisible to Part---ie a[[4]] was happy
> to give the result "b"
> (3) why was it also invisible to Length?
> (4) why does even FullForm[a] and InputForm[a]
> not acknowledge the presence of the Sequence head?
>
> what i am trying to avoid is copying the list a. for my real
> problem a is a large complicated list with lots of substructure;
> since i know exactly which bit i want to change, i thought
> it would just be a matter of updating a few pointers (i was a
> lisp programmer many moons ago).
>
> a friend suggests that i use Flatten, and rely on the clever
> internal routines that spot when there is duplication;
> but look at the following:
>
> data = Table[Random[], {100000}];
> {MemoryInUse[], MaxMemoryUsed[]}/1024//Round
> data[[654]] = {0.3,0.4,0.5};
> {MemoryInUse[], MaxMemoryUsed[]}/1024//Round
> data = Flatten[data,1];
> {MemoryInUse[], MaxMemoryUsed[]}/1024//Round
>
> gives the following output:
>
> {1926, 1934}
> {3897, 3904}
> {3897, 4776}
>
> there is a big increase in memory use at the element replacement,
> sort of indicating that the data was copied then; true enough,
> there is not much of an increase after the Flatten[], so maybe
> it is clever.
>
> to quote form dave wagner's book on "power programmin with Mathematica the
> kernel"
> it says on page 305 with a "be alert" icon:
>
> "the problem with building up lists an element at a time is that Mathematica
> lists
> are implemented as arrays. the advantage of this implementation is that
> a list can be randomly indexed in time that is independent of the length
> of a list...."
>
> i just tried it, and it is true: so things aren't as easy as
> maniplulating
> a few pointers in lisp. i wasn't a lert before, but i am one now.
>
> so, are there any efficient (ie non-copying) ways of modifying an
> existing
> list?
>