MathGroup Archive 2003

[Date Index] [Thread Index] [Author Index]

Search the Archive

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



  • Prev by Date: AW: Desciphering Solve[] output.
  • Next by Date: AW: Problem for exponent and indice
  • Previous by thread: pattern matching with repeated named patterns
  • Next by thread: Re: pattern matching with repeated named patterns