Re: Basic questions on list manipulation in the
- To: mathgroup at smc.vnet.net
- Subject: [mg95672] Re: Basic questions on list manipulation in the
- From: "Drago Ganic" <dganic at vodatel.net>
- Date: Sat, 24 Jan 2009 06:20:53 -0500 (EST)
- References: <200901211145.GAA12433@smc.vnet.net> <gl9n4c$as3$1@smc.vnet.net>
Hi, What you want is basically the relational database update/modify operator in Mathematica and this whole area is IMHO Mathematica's weakness since V1. There is no build-in function for this and related operations and area of computer science (DatabaseLink` stores the data externally, so I don't count it here). The list structure and operations are too general for a large class of applications and a less general but powerfull structure for tables/relations is needed. The closest thing done in this regard was Roman E. Maeder's article in the Mathematica Journal and the chapter "Databases" in his books: - The Mathematica Programmer, 1994 - Computer Science with Mathematica, 2000 In those books the (same) package Database` is developed and documented. Maeder showed the way how this operation should be implemented in Mathematica , but did not work out the details (operators like Sort, Group, Delete, Insert etc.) In your example (and ever imaginable similar example according to relational database theory), the data should be presented in a table form (matrix with header row) which lists all the attributes of your entities and where some attributes identify your entities (so called keys) while all other just describe it. But it is important that for many purposes keys can be used as all other attributes. For example the set to be updated can be defined in any way, not only via the key. In your example sym would be the key (e.g. Name), where val1, val2 and val3 would be the other attributes (e.g. height, weight, salary etc.). We load the package: In[1]: = <<Database` Create the table/relation: In[2]:= rel= tbl= newRelation[ {sym, val1, val2, val3},{ {sym1, 20, 300, 1000}, {sym2, 50, 500, 20000} }] Out[2]= R[{sym,val1,val2,val3},{{sym1,20,300,1000},{sym2,50,500,20000}}] The Modify function from the package modifies *all* data: In[3]:= Modify [ val1 = "Hello", tbl ] Out[3] = R[{sym,val1,val2,val3},{{sym1,Hello,300,1000},{sym2,Hello,500,20000}}] To modify/update a subset of the data, we overload Modify: In[4]:= Modify [ val1 = "Hello", {rel, sym == sym1} ] Out[4] = R[{sym,val1,val2,val3},{{sym1,Hello,300,1000},{sym2,50,500,20000}}] Here is the code of the overloaded function: Modify[ assignment_, {rel_Symbol, cond_} ] := Module[ {temp, rest}, temp = Select[ rel, cond ]; rest = Complement[ rel, temp ]; Modify[ assignment, temp ]; rel = Union [ temp, rest ] ] Notes: - the package Database` must be slightly modified for Mathematica versions above 5.1 (because of new build-in functions Tuples, InputField) - notice the nice set/relation-oriented programming style in Modify. No positional notation, no pure functions (# &) etc. - the condition could be any predicate .. like Sqrt[val2] > 100 not just simple ones like sym == sym1 Best regards from Croatia, Drago Ganic "DrMajorBob" <btreat1 at austin.rr.com> wrote in message news:gl9n4c$as3$1 at smc.vnet.net... > For instance, > > ct = {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> 50, val2 -> 500, > val3 -> 20000}}}; > > changeVal[ct_, who_, class_, amt_] := > ct /. Rule[who, {a___, Rule[class, _], b___}] :> > Rule[who, {a, Rule[class, amt], b}] > > ct = changeVal[ct, sym2, val1, "hello"] > > {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> "hello", val2 -> 500, > val3 -> 20000}}} > > If you don't like the assignment construct "ct = changeVal[..]", an > alternative is > > ct = {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> 50, val2 -> 500, > val3 -> 20000}}}; > > Clear[changeVal] > SetAttributes[changeVal, HoldFirst] > changeVal[ct_, who_, class_, amt_] := > ct = ct /. > Rule[who, {a___, Rule[class, _], b___}] :> > Rule[who, {a, Rule[class, amt], b}] > > changeVal[ct, sym2, val1, "hello"]; > ct > > {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> "hello", val2 -> 500, > val3 -> 20000}}} > > If you want changeVal to treat ct as a global, not an argument (never > recommended), then: > > ct = {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> 50, val2 -> 500, > val3 -> 20000}}}; > > Clear[changeVal] > changeVal[who_, class_, amt_] := > ct = ct /. > Rule[who, {a___, Rule[class, _], b___}] :> > Rule[who, {a, Rule[class, amt], b}] > > changeVal[sym2, val1, "hello"]; > ct > > {{sym1 -> {val1 -> 20, val2 -> 300, > val3 -> 1000}}, {sym2 -> {val1 -> "hello", val2 -> 500, > val3 -> 20000}}} > > Bobby > > On Wed, 21 Jan 2009 05:45:28 -0600, <dangerrity at gmail.com> wrote: > >> Hello, >> >> I have some basic questions about using lists in Mathematica. >> Specifically I have a table that serves as sort of a database with the >> following structure: >> >> ct = { >> { sym1 -> {val1->20, val2->300, val3->1000, ... }, >> { sym2 -> {val1->50, val2->500, val3->20000,...}, >> ... >> } >> >> sym1, sym2, ... are people and val1, val2 ... represent attributes of >> each person. >> >> Now I'm trying to go in and modify values. I can do it, but I think >> not well and I think with a "programming language" mindset instead of >> a "Mathematica mindset." >> >> Here is my specific question. In order to change a specific value in >> the list above (valxxx) for a given individual (symxxx), I created >> this function: >> >> changeVal[ who_, class_, amnt_ ] := ( >> ct[[ Position[ ct, who ][[ 1, 1 ]], 2 ]] = >> ReplacePart[ ct[[ Position[ ct, who ][[ 1, 1 ]], 2 ]], >> Position[ ct[[ Position[ ct, who ][[ 1, 1 ]] ]], class ][[ 1, >> 2 ]] -> (class -> amnt) ] >> ); >> >> Now I know there is a better way than that using list manipulation and >> patterns. Can some of you experienced pros help me out? I call this >> "write only" code because I don't know that I could explain it once >> it's written. >> >> Perhaps a more fundamental question: is this the right way to store >> data in lists? Or would it be better to just have the values and >> reference them by index number? >> >> Thanks for your patience with a simple question. >> >> > > > > -- > DrMajorBob at longhorns.com >