Pattern to match only “children” of certain elements

后端 未结 4 2054
隐瞒了意图╮
隐瞒了意图╮ 2020-12-09 21:44

I would like to be able to have a pattern that matches only expressions that are (alternately: are not) children of certain other elements.

For example, a pattern to

4条回答
  •  清歌不尽
    2020-12-09 22:28

    According to your explanation in the comment to the acl's answer:

    Actually I'd like it to work at any level in the expression <...>. <...> what I need is replacement: replace all expression that match this "pattern", and leave the rest unchanged. I guess the simplest possible solution is finding the positions of elements, then using ReplacePart. But this can also get quite complicated in the end.

    I think it could be done in one pass with ReplaceAll. We can rely here on the documented feature of the ReplaceAll: it does not look at the parts of the original expression which were already replaced even if they are replaced by themselves! Citing the Documentation: "ReplaceAll looks at each part of expr, tries all the rules on it, and then goes on to the next part of expr. The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts."

    Here is my solution (whatIwant is what you want to do with matched parts):

    replaceNonChildren[lst_List] := 
     ReplaceAll[#, {x_List :> whatIwant[x], y_ :> y}] & /@ lst
    

    Here is your test case:

    replaceNonChildren[{{1, 2, 3}, Graphics[Line[{{1, 2}, {3, 4}}]]}] // InputForm
    
    => {whatIwant[{1, 2, 3}], Graphics[Line[{{1, 2}, {3, 4}}]]}

    Here is a function that replaces only inside certain head (Graphics in this example):

    replaceChildren[lst_List] := 
     ReplaceAll[#, {y : Graphics[__] :> (y /. x_List :> whatIwant[x])}] & /@ lst
    

    Here is a test case:

    replaceChildren[{{1, 2, 3}, Graphics[Line[{{1, 2}, {3, 4}}]]}] // InputForm
    
    => {{1, 2, 3}, Graphics[Line[whatIwant[{{1, 2}, {3, 4}}]]]}

提交回复
热议问题