RE: pattern matching with repeated named patterns
- To: mathgroup at smc.vnet.net
- Subject: [mg39829] RE: [mg39808] pattern matching with repeated named patterns
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Sat, 8 Mar 2003 02:48:38 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
>-----Original Message----- >From: Gara Kuta [mailto:garakuta at f2s.com] To: mathgroup at smc.vnet.net >Sent: Friday, March 07, 2003 9:43 AM >To: mathgroup at smc.vnet.net >Subject: [mg39829] [mg39808] pattern matching with repeated named patterns > > >Hi >I have a list of data records which are all of the same type, for >example person:{name_Sting, sex:M|F, age_Integer, weight_?((1<#<500)&)}. >I want to access the different fields so I have given them names in the >pattern. I have a list of these records and I want to use pattern >matching to test the the whole list such as >{person:{name_Sting, sex:M|F, age_Integer, weight_?((1<#<500)&)}...} >but once you name the parts of the pattern, they have to be the same for >every record. I could leave the names out and use a pattern like >{{_Sting, M|F, _Integer, _?((1<#<500)&)}...} >which matches different records with the same structure but then I can't >access the field values by name. Is there any way I can do both at once? >Thanks >G > > > > > Reformulate your problem. See e.g. In[1]:= alist = {{"Adam", M, 38, 73}, {"Eve", F, 37, 65.5}, {"Kain", M, 17, 501}, {Abel, M, 15, 58}}; In[2]:= ToString[Count[alist, person : {name_String, sex : M | F, age_Integer, weight_?(1 <= # <= 500 &)} /; (Print["Name: ", name, "\nSex ", sex, "\nAge = ", age, "\nweight is ", weight]; True)]] <> " matches out of " <> ToString[Length[alist]] >From In[2]:= Name: Adam Sex M Age = 38 weight is 73 >From In[2]:= Name: Eve Sex F Age = 37 weight is 65.5 Out[2]= "2 matches out of 4" If a name appears in a pattern it must get the same value for each occurance, else the pattern as a whole cannot match: In[6]:= MatchQ[{{"Adam", M, 38, 73}, {"Adam", M, 38, 73}, {"Eve", F, 37, 65.5}, {"Adam", M, 38, 73},}, {({name_String, sex : M | F, age_Integer, weight_?(1 <= # <= 500 &)} /; (Print["Name: ", name, "\nSex ", sex, "\nAge = ", age, "\nweight is ", weight]; True)) ...}] >From In[6]:= Name: Adam Sex M Age = 38 weight is 73 >From In[6]:= Name: Adam Sex M Age = 38 weight is 73 Out[6]= False Here you see how Adam is matched at his first occurrance and the pattern variables get their values, which then are printed. The next list element matches because now all values of all pattern variables match, that match then issues the second print. After that "Eve" doesn't match to "Adam" and the pattern as whole won't match and thus is abandoned, the third occurrance of Adam will not be considered. Perhaps you also might be interested in this observation: In[18]:= MatchQ[{{"Adam", M, 38, 73}, {"Adam", M, 38, 73}, {"Eve", F, 37, 65.5}, {"Adam", M, 38, 73},}, {_?(MatchQ[#, Null | {name_String, sex : M | F, age_Integer, weight_?(1 <= # <= 500 &)} /; (Print["Name: ", name, "\nSex ", sex, "\nAge = ", age, "\nweight is ", weight]; True)] &) ...}] >From In[18]:= Name: Adam Sex M Age = 38 weight is 73 >From In[18]:= Name: Adam Sex M Age = 38 weight is 73 >From In[18]:= Name: Eve Sex F Age = 37 weight is 65.5 >From In[18]:= Name: Adam Sex M Age = 38 weight is 73 >From In[18]:= Name: Sex Age = weight is Out[18]= True Here the pattern for the element has no name, hence each element in the List will be tried. This (matched) element then will be matched to constituents as part of the PatternTest (?test). We included Null into that pattern as Null is tried for RepeatedNull (or Repeated) and MatchQ then gives True. The pattern variables of the constituents, however, don't get a value in this case, as you see. Had we not included Null into that test, all persons still would have been printed, but the pattern as a whole would have failed. You also might like to look at: MatchQ[Join[ alist, {{"Adam", M, 38, 73}}], {_?((MatchQ[#1, Null | {name_String, sex : (M | F), age_Integer, weight_?(1 <= #1 <= 500 &)} /; (Print["Name: ", name, "\nSex ", sex, "\nAge = ", age, "\nweight is ", weight]; True)]; True) &) ...}] The most simple application might be just to use the pattern as filter for those records which qualify, or don't: In[31]:= Cases[alist, person : {name_String, sex : M | F, age_Integer, weight_?(1 <= # <= 500 &)}] Out[31]= {{"Adam", M, 38, 73}, {"Eve", F, 37, 65.5}} In[33]:= Cases[alist, _?(! MatchQ[#, {name_String, sex : M | F, age_Integer, weight_?(1 <= # <= 500 &)}] &)] Out[33]= {{"Kain", M, 17, 501}, {Abel, M, 15, 58}} -- Hartmut Wolf