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