Re: Re: Re: Set in Scan
- To: mathgroup at smc.vnet.net
- Subject: [mg22045] Re: [mg22008] Re: [mg21900] Re: [mg21856] Set in Scan
- From: Hartmut Wolf <hwolf at debis.com>
- Date: Fri, 11 Feb 2000 02:38:25 -0500 (EST)
- References: <200002100725.CAA05624@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
Dear Tomas, Tomas Garza schrieb: > > It looks as if the suggested approach of Hartmut Wolf's - as well as Jens > Peer Kuska's - to this problem works fine and is extremely efficient. > However, suppose that instead of having a few possibly very long lists {v1, > v2, v3} one has a large number N - perhaps of the order of tens of > thousands - of such lists, which need not be too long. The procedure would > have to be modified In fact! This is a different problem, and it's for this one indeed, that the second proposal I made -- as Allan Hayes did -- comes to full strength. Perhaps you might go back in this thread to Allan's answer, to see that the elements of the compound object, the lists v<i> even need not be of same length, *however* all v<i> must be long enough to at least include the replace position, else nothing will be replaced at all. To do the replacement only in those sublists being long enough would again consitute another problem. > ... in order to use some symbol like allv = {v1, v2,..., vN} > in Scan, instead of writing the complete list with all individual v's, as > used by Hartmut and Jens: > > Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}], > Unevaluated[{v1, v2, v3}]] > > However, if I write > > Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}], > Unevaluated[allv]] > > nothing happens. It can't, because Unevaluated reaches to Scan (i.e. to it's procedural machinery) the unevaluated symbol allv, and if you scan a symbol nothing happens. Scan doesn't even look at the Head of an expression, even be it Hold -- as Allan noticed -- instead it feeds on the elements, yet there are none in this case. It's only that OwnValues[allv] {HoldPattern[allv] :> {{0.308624, 0.0113816, 0.452114, 0.100156}, {0.368705, 0.44588, 0.878839, 0.736246}, {0.71764, 0.18652, 0.667573, 0.338795}}} has such elements. > ... And the second suggestion by Hartmut is unusable in case > the assignment may be something which depends on the value of the element to > be replaced, e.g. Function[sym,If[sym[[3]] < 0.5, "-XXX-","-YYY-"]]. > Well again this is not quite the same problem, but there is a natural extending solution: Scan[Function[sym, sym[[3]] = If[sym[[3]] < 0.5, "-XXX-", "-YYY-"], {HoldFirst}], Unevaluated[{v1, v2, v3}]] {v1, v2, v3} {{0.308624, 0.0113816, "-XXX-", 0.100156}, {0.368705, 0.44588, "-YYY-", 0.736246}, {0.71764, 0.18652, "-YYY-", 0.338795}} > Any suggestions? > More along the lines of this discussion you would like to try Scan[Function[sym, (#[[3]] = If[#[[3]] < 0.5, "-XXX-", "-YYY-"])&@ Unevaluated[sym], {HoldFirst}], Unevaluated[{v1, v2, v3}]] Or the somewhat more obfuscated Scan[Evaluate, Scan[((#[[3]] = If[#[[3]] < 0.5, "-XXX-", "-YYY-"])& @Unevaluated[#])&, Unevaluated /@ Unevaluated[{v1, v2, v3}]]] no Hold attributes in. This even works when you replace the outer Scan (to get the replaced elements evaluated) by Map although the inner Scan doesn't return anything. I guess this is neither a bug nor any intended use (of Map), but a consequence of the requirement that repeated Scans should be possible. This example at least is an argument that they should! When had I looked for a solution to the problem posed originally by Johannes Ludsteck that ideom Unevaluated /@ Unevaluated[{v1,v1,v3}] came up to my mind shortly after I had sent off my reply Scan[(#[[3]] = -the new value-)&, Unevaluated /@ Unevaluated[{v1, v2, v3}]] ... only to then learn from Allan Hayes Scan[(#[[3]] = -the new value-)&, Unevaluated /@ Hold[v1, v2, v3]] At the time of my reply I had no time for measurement and guessed the time complexity to be O[constant]. Now I did some comparitative measurements, each with a new kernel, so having the same memory and history conditions: --------- In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}]; In[2]:= Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}], Unevaluated[{v1, v2, v3}]] // Timing Out[2]= {1.071 Second, Null} In[3]:= Take[#, 4] & /@ {v1, v2, v3} Out[3]= {{0.675382, 0.55102, "-XXX-", 0.633244}, {0.422611, 0.715315, "-XXX-", 0.426188}, {0.011633, 0.223577, "-XXX-", 0.240954}} --------- In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}]; In[2]:= Scan[Function[sym, sym[[3]] = "-YYY-"], Unevaluated /@ Unevaluated[{v1, v2, v3}]] // Timing Out[2]= {1.062 Second, Null} In[3]:= Take[#, 4] & /@ {v1, v2, v3} Out[3]= {{0.974173, 0.96568, "-YYY-", 0.747727}, {0.910969, 0.312475, "-YYY-", 0.34289}, {0.729062, 0.611829, "-YYY-", 0.437515}} --------- In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}]; In[2]:= Scan[(#[[3]] = "-ZZZ-") &, Unevaluated /@ Hold[v1, v2, v3]] // Timing Out[2]= {1.062 Second, Null} In[3]:= Take[#, 4] & /@ {v1, v2, v3} Out[3]= {{0.921074, 0.870566, "-ZZZ-", 0.553795}, {0.198232, 0.688503, "-ZZZ-", 0.372325}, {0.799497, 0.21537, "-ZZZ-", 0.0673068}} plus yet another variant In[1]:= Clear[f]; Attributes[f] = {HoldFirst}; In[2]:= f[sym_] := (sym[[3]] = "-WWW-") In[3]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}]; In[4]:= Scan[f, Hold[v1, v2, v3]] // Timing Out[4]= {1.032 Second, Null} In[5]:= Take[#, 4] & /@ {v1, v2, v3} Out[5]= {{0.422896, 0.178604, "-WWW-", 0.193691}, {0.184583, 0.524976, "-WWW-", 0.370107}, {0.592243, 0.952171, "-WWW-", 0.79216}} All four perform the same and are O[x], when x is the length of the lists! I admit, I don't understand that. The Question is: what did we measure? The Performance of the functions? -- obviously not. The performance of Scan (through a list of three elements)? -- probably not. Seems just to be the time of accessing the 3rd element of a list. See In[1]:= {v1, v2, v3} = Table[Random[], {3}, {1000000}]; In[2]:= {v1[[3]], v2[[3]], v3[[3]]} // Timing Out[2]= {0. Second, {0.969595, 0.192005, 0.637547}} In[3]:= {v1[[3]] = "-UUU-", v2[[3]] = "-UUU-", v3[[3]] = "-UUU-"} // Timing Out[3]= {1.052 Second, {"-UUU-", "-UUU-", "-UUU-"}} So it's Set[Part[...],...] which is not O[constant] Kind regards, Hartmut ------------------------------------------------------------ P.S.: I used the same values for allv, v<i> as before, see: > Hartmut Wolf wrote: > > > Johannes Ludsteck schrieb: > > > > > > Dear MathGroup members > > > > > > I have to do replacements in very long lists. An efficient way to do > > > this is to use > > > > > > x[[index]]=newElement. > > > > > > This, however, doesn't work if I want to do replacements for a set of > > > lists. If I try to replace the third element in the lists v1, > > v2 and v3 by > > > typing > > > > > > Scan[#[[3]] = newElement &, {v1,v2,v3}] > > > I get the error message > > > Set::setps: #1 in assignment of part is not a symbol. > > > > > > > Hallo Johannes, > > > > the problem with your expression is to get the symbols v1,... > > unevaluated into the lhs of Set. There are two points where evaluation > > occurs, first at the rhs of Scan (or Map) where the list {v1,v2,v3} and > > then recursively v1,... are evaluated. You can suppress that by wrapping > > the list with Unevaluated. The second is the evaluation of #1 before > > Function inserts the argument at the lhs of Set. This can be avoided by > > specifing the argument HoldFirst for evaluation of Function: > > > > In[8]:= allv = {v1, v2, v3} = Table[Random[], {3}, {4}] > > Out[8]= > > {{0.308624, 0.0113816, 0.452114, 0.100156}, > > {0.368705, 0.44588, 0.878839, 0.736246}, > > {0.71764, 0.18652, 0.667573, 0.338795}} > > > > In[9]:= > > Scan[Function[sym, sym[[3]] = "-XXX-", {HoldFirst}], > > Unevaluated[{v1, v2, v3}]] > > > > In[10]:= {v1, v2, v3} > > Out[10]= > > {{0.308624, 0.0113816, "-XXX-", 0.100156}, > > {0.368705, 0.44588, "-XXX-", 0.736246}, > > {0.71764, 0.18652, "-XXX-", 0.338795}} > > > > Yet another idea would be to use the compound object allv (see above), > > and then > > > In[11]:= allv[[All, 2]] = "-YYY-" > > Out[11]= "-YYY-" > > > > In[14]:= allv > > Out[14]= > > {{0.308624, "-YYY-", 0.452114, 0.100156}, > > {0.368705, "-YYY-", 0.878839, 0.736246}, > > {0.71764, "-YYY-", 0.667573, 0.338795}} > > > > Of course the values of v1,... are not affected, but perhaps you may > > dispense with them alltogether, or use them only for access or display > > purposes: > > > > In[15]:= Clear[v1, v2, v3] > > In[16]:= > > v1 := allv[[1]]; v2 := allv[[2]]; v3 := allv[[3]] > > > > In[17]:= {v1, v2, v3} > > Out[17]= > > {{0.308624, "-YYY-", 0.452114, 0.100156}, > > {0.368705, "-YYY-", 0.878839, 0.736246}, > > {0.71764, "-YYY-", 0.667573, 0.338795}}
- References:
- Re: Re: Set in Scan
- From: "Tomas Garza" <tgarza@mail.internet.com.mx>
- Re: Re: Set in Scan