Re: Efficient way to merge lists--Programming help
- To: mathgroup at smc.vnet.net
- Subject: [mg12730] Re: [mg12708] Efficient way to merge lists--Programming help
- From: Daniel Lichtblau <danl>
- Date: Thu, 4 Jun 1998 02:52:15 -0400
- References: <199806030620.CAA14325@smc.vnet.net.>
- Sender: owner-wri-mathgroup at wolfram.com
Joel Cannon wrote: > > Cam someone suggest better ways to accomplish the following? > > I have two lists containing triplets--test is a rectangular array of > triplets {x,y,z} (e.g. Dimensions {4,40,3}) and test2 is an array of > triplets (e.g. Dimensions {50,3}). test2 is to replace equivalent > elements in test (when the x and y values are equal--the test2 z values > have been calculated more accurately). > > The task can be understood to be: > > 1. Given a triplet {x_i,y_i,z_i} from test2, find the position in test > which has the same {x_i,y_i,_}. > > 2. Replace the element in test by the triplet from test2. > > I resorted to a loop after I decided that it would take me too much time > to figure out a better, more elegant solution. Here is what I did: > > For[i=1,i<=Length[test2],i++, > test = ReplacePart[test,test2[[i]], > test//Position[#,{test2[[i]][[1]],test2[[i]][[2]],_}]& //Flatten]]; > > Thanks for any help. > > ------------------------------------------------------------------------------ > Joel W. Cannon | (318)869-5160 Dept. of > Physics | (318)869-5026 FAX Centenary College of > Louisiana | P. O. Box 41188 | > Shreveport, LA 71134-1188 | > One way is just to use simple replacement rules. I'll create some triples, use Union to discard those that replicate {x,y} coordinates. I'll also create a matrix of data. triples = Table[ {Random[Integer,10],Random[Integer,10],Random[Real,86]}, {50}]; triples = Union[triples, SameTest->(Drop[#1,-1]===Drop[#2,-1]&)] data = Table[ {Random[Integer,10],Random[Integer,10],Random[Real,99]}, {4}, {40}]; Now we create a list of rules and do the relacement. Clear[rules1]; rules1 = triples /. {x_,y_,z_} -> ({x,y,_}->{x,y,z}); data2 = data /. rules1; For larger sets this is not necessarily efficient because it relies on alot of pattern matching. You could instead set up a loop to hash the replacement triples, then loop over the data doing the replacements. These "loops" are perhaps best achieved using Table (but see what other respondents have to say). I use Module to encapsulate all local variables except rule (the "head" for our hash table entries). So this variable needs to be cleared before use. If you don't believe that, try debugging this without clearing it. The In/Out numbers below give some measure of how long it took me to catch on. Clear[rule]; Module[{x,y,z}, Table[{x,y,z}=triples[[j]]; rule[x,y] = z, {j,Length[triples]}]]; repair[data_] := Module[{x,y,z,z2}, Table[ {x,y,z} = data[[j,k]]; If [NumberQ[z2 = rule[x,y]], {x,y,z2}, {x,y,z}], {j,Length[data]}, {k,Length[data[[1]]]}] ] data3 = repair[data]; In[90]:= data2===data3 Out[90]= True To compare speed I'll try this on a larger example. newdata = Table[ {Random[Integer,10],Random[Integer,10],Random[Real,99]}, {40}, {4000}]; In[17]:= Timing[newdata2 = newdata /. rules1;] Out[17]= {51.41 Second, Null} In[18]:= Timing[newdata3 = repair[newdata];] Out[18]= {17.02 Second, Null} In[19]:= newdata3===newdata2 Out[19]= True Alternatively we can map a pure function over the data. This is a hair faster still. In[30]:= Timing[newdata4 = Map[ If [NumberQ[z=rule[#[[1]],#[[2]]]], {#[[1]],#[[2]],z}, #]&, newdata, 2];] Out[30]= {16.23 Second, Null} In[31]:= newdata4 === newdata3 Out[31]= True Now that I've turned this into a comparative timing test I expect you'll get some responses that are measurably faster still. Daniel Lichtblau Wolfram Research
- References:
- Efficient way to merge lists--Programming help
- From: Joel Cannon <cannon@alpha.centenary.edu>
- Efficient way to merge lists--Programming help