MathGroup Archive 1999

[Date Index] [Thread Index] [Author Index]

Search the Archive

Q: efficient in-place list element replacement?

  • To: mathgroup at smc.vnet.net
  • Subject: [mg21091] Q: efficient in-place list element replacement?
  • From: simon shannon <sshannon at taz.dra.hmg.gb>
  • Date: Sun, 12 Dec 1999 23:51:59 -0500 (EST)
  • Organization: dera
  • Sender: owner-wri-mathgroup at wolfram.com

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?

            any comments welcome

               - simon shannon


  • Prev by Date: Re: NonLinearFit
  • Next by Date: Unexpected behavior with Thread
  • Previous by thread: Re: NonLinearFit
  • Next by thread: Re: Q: efficient in-place list element replacement?