2
$\begingroup$

Consider the following Pattern expression:

keysLevel1Pattern={_,
    XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h2",{"class"->"level-title"},{x_,XMLElement[_,_,{y_}],_}],_}],_}],
    _,
    XMLElement[_,_,{_,
        PatternSequence[XMLElement[_,_,{_,_,_,_,XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h3",{"class"->"course-title"},{_}],_,_,_,_,_}],_,_,_}],_}],
        _]..
    }],
_}:>StringRiffle@StringTrim[{x,y}]->{};

If I run it as follows it works fine and is able to capture all the required sub expressions:

Cases[pageXML,keysLevel1Pattern,∞]

But I want to exact something from each PatternSequence that matches and collect it in a list. So I try the following modification:

keysLevel1Pattern={_,
    XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h2",{"class"->"level-title"},{x_,XMLElement[_,_,{y_}],_}],_}],_}],
    _,
    XMLElement[_,_,{_,
        PatternSequence[XMLElement[_,_,{_,_,_,_,XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h3",{"class"->"course-title"},{z_}],_,_,_,_,_}],_,_,_}],_}],
        _]..
    }],
_}:>StringRiffle@StringTrim[{x,y}]->{z};

But this doesn't work.

So my question is, is there a way to nicely refer to each z that matches in the PatternSequence without using nested Cases?

$\endgroup$

1 Answer 1

3
$\begingroup$

As long as the structure is fixed enough, you can capture the entire PatternSequence into a single named Pattern (:), and use Part ([[…]]) with a Span-type (;;) part-specification to extract the relevant parts:

list = {
   {1, {2, 3, 4, 5, 6, 7}},
   {4, {3, 4, 5, 6, 7, 1}},
   {5, {1, 4, 5, 6, 8, 1}}
   };

pat = {x_, {s : PatternSequence[_, _] ..}} :> x -> {s}[[;; ;; 2]];

Cases[list, pat]
(* {1 -> {2, 4, 6}, 4 -> {3, 5, 7}, 5 -> {1, 5, 8}} *)

The above extracts every second element from the Repeated pattern, i.e. the left element from each PatternSequence match.

In your case, the part specification is more complicated, since you have a deeply nested pattern. You can use Position to help you find the part specification:

Position[Verbatim[z_]]@PatternSequence[XMLElement[_, _, {_, _, _, _, XMLElement[_, _, {_, XMLElement[_, _, {_, XMLElement["h3", {"class" -> "course-title"}, {z_}], _, _, _, _, _}], _, _, _}], _}], _]
(* {{1, 3, 5, 3, 2, 3, 2, 3, 1}} *)

So your pattern would look like this (keeping in mind that the first 1 above should be ;;;;2):

keysLevel1Pattern={_,
    XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h2",{"class"->"level-title"},{x_,XMLElement[_,_,{y_}],_}],_}],_}],
    _,
    XMLElement[_,_,{_,
        z:PatternSequence[XMLElement[_,_,{_,_,_,_,XMLElement[_,_,{_,XMLElement[_,_,{_,XMLElement["h3",{"class"->"course-title"},{_}],_,_,_,_,_}],_,_,_}],_}],
        _]..
    }],
_}:>StringRiffle@StringTrim[{x,y}]->{z}[[;; ;; 2, 3, 5, 3, 2, 3, 2, 3, 1]];
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.