Re: Q: efficient in-place list element replacement?
- To: mathgroup at smc.vnet.net
- Subject: [mg21200] Re: [mg21091] Q: efficient in-place list element replacement?
- From: "Mark Harder" <harderm at ucs.orst.edu>
- Date: Fri, 17 Dec 1999 01:24:43 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
Simon, Is this efficient enough? ExpandAt[x_List,y_List,M_Integer]:= Module[{seq=Sequence @@ x},(seq[[M]]= Sequence @@ y; Return[List[seq ] ];) ]; (MultiLink) In[113]:= ExpandAt[{1,2,3,4,5}, {"a","b","c"},4] (MultiLink) Out[113]= {1,2,3,"a","b","c",5} (MultiLink) In[114]:= %[[7]] (MultiLink) Out[114]= 5 -mark P.S. MultiLink is just the name of my current Kernel; ignore it. - -----Original Message----- From: simon shannon <sshannon at taz.dra.hmg.gb> To: mathgroup at smc.vnet.net Subject: [mg21200] [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? > > any comments welcome > > - simon shannon >