wolfram-mathematica - 仅匹配某些元素的 "children"的模式

标签 wolfram-mathematica pattern-matching

我希望能够有一种模式,该模式仅匹配是(另选:不是)某些其他元素的子代的表达式。

例如,用于匹配不在List对象内的所有Graphics的模式:

{ {1,2,3}, Graphics[Line[{{1,2},{3,4}}]] }

此模式将匹配{1,2,3},但不匹配{{1,2},{3,4}}

提取符合这些条件的表达式有相对简单的方法,但是模式不仅用于提取,而且还用于替换,这是我在这里的主要用例(ReplaceAll)。

您知道执行此操作的任何简单,简明和通用的方法吗?

仅使用模式是否有可能做到这一点?

最佳答案

我将提出一种基于表达式预处理和使用规则的操作的软重新定义而不是规则本身的解决方案。这是代码:

ClearAll[matchChildren, exceptChildren];
Module[{h, preprocess},
  preprocess[expr_, parentPtrn_, lhs_, match : (True | False)] :=
     Module[{pos, ptrnPos, lhsPos},
       ptrnPos = Position[expr, parentPtrn];
       lhsPos = Position[expr, lhs];
       pos = Cases[lhsPos, {Alternatives @@ PatternSequence @@@ ptrnPos, __}];
       If[! match,pos = Complement[Position[expr, _, Infinity, Heads -> False], pos]];
       MapAt[h, expr, pos]];

  matchChildren /: 
    fun_[expr_, matchChildren[parentPtrn_, lhs : Except[_Rule | _RuleDelayed]],
    args___] :=
       fun[preprocess[expr, parentPtrn, lhs, True], h[lhs], args] //. 
           h[x_] :> x;

  matchChildren /: 
    fun_[expr_, matchChildren[parentPtrn_, lhs_ :> rhs_], args___] :=
       fun[preprocess[expr, parentPtrn, lhs, True], h[lhs] :> rhs, args] //. 
           h[x_] :> x;

  exceptChildren /: 
   fun_[expr_,exceptChildren[parentPtrn_, lhs : Except[_Rule | _RuleDelayed]], 
   args___] :=
       fun[preprocess[expr, parentPtrn, lhs, False], h[lhs], args] //. 
           h[x_] :> x;

  exceptChildren /: 
   fun_[expr_, exceptChildren[parentPtrn_, lhs_ :> rhs_], args___] :=
       fun[preprocess[expr, parentPtrn, lhs, False], h[lhs] :> rhs, args] //. 
          h[x_] :> x;
]

有关实现思路及其工作原理的一些详细信息。这个想法是,为了限制应该匹配的模式,我们可以将此模式包装在某个头部(例如h),也可以将所有与原始模式匹配但也(或不存在)在其他元素内的元素包装(与“parent”模式匹配)在同一头h中。可以针对通用的“子”模式执行此操作。从技术上讲,使之成为可能的一件事是规则应用程序的侵入性(和函数参数传递,这方面具有相同的语义)。这样一来,可以采用类似于x_List:>f[x]的规则,并与通用模式lhs_:>rhs_匹配,然后通过使用h[x_List]:>f[x]将其更改为h[lhs]:>rhs。这是不平凡的,因为RuleDelayed是范围界定结构,并且只有另一个RuleDelayed的侵入性(或函数参数传递)才允许我们进行必要的范围手术。从某种意义上讲,这是一个构造性使用示例的示例,该效果导致在Mathematica中产生leaky functional abstraction。这里的另一个技术细节是使用UpValues重载以“软”方式使用规则(CasesReplaceAll等)的函数,而不向其添加任何规则。同时,这里的UpValues允许该代码具有通用性-一种代码提供了许多使用模式和规则的功能。最后,我将Module变量用作封装机制,以隐藏辅助头h和函数preprocess。通常,这是一种非常方便的方法,既可以实现封装功能,又可以封装小于数据包但大于单个功能的数据。

这里有些例子:
In[171]:= expr = {{1,2,3},Graphics[Line[{{1,2},{3,4}}]]};

In[168]:= expr/.matchChildren[_Graphics,x_List:>f[x]]//FullForm
Out[168]//FullForm= List[List[1,2,3],Graphics[Line[f[List[List[1,2],List[3,4]]]]]]

In[172]:= expr/.matchChildren[_Graphics,x:{__Integer}:>f[x]]//FullForm
Out[172]//FullForm= List[List[1,2,3],Graphics[Line[List[f[List[1,2]],f[List[3,4]]]]]]

In[173]:= expr/.exceptChildren[_Graphics,x_List:>f[x]]//FullForm
Out[173]//FullForm= List[f[List[1,2,3]],Graphics[Line[List[List[1,2],List[3,4]]]]]

In[174]:= expr = (Tan[p]*Cot[p+q])*(Sin[Pi n]+Cos[Pi m])*(Tan[q]+Cot[q]);

In[175]:= expr/.matchChildren[_Plus,x_Tan:>f[x]]
Out[175]= Cot[p+q] (Cot[q]+f[Tan[q]]) (Cos[m \[Pi]]+Sin[n \[Pi]]) Tan[p]

In[176]:= expr/.exceptChildren[_Plus,x_Tan:>f[x]]
Out[176]= Cot[p+q] f[Tan[p]] (Cos[m \[Pi]]+Sin[n \[Pi]]) (Cot[q]+Tan[q])

In[177]:= Cases[expr,matchChildren[_Plus,x_Tan:>f[x]],Infinity]
Out[177]= {f[Tan[q]]}

In[178]:= Cases[expr,exceptChildren[_Plus,x_Tan:>f[x]],Infinity]
Out[178]= {f[Tan[p]]}

In[179]:= Cases[expr,matchChildren[_Plus,x_Tan],Infinity]
Out[179]= {Tan[q]}

In[180]:= Cases[expr,matchChildren[_Plus,x_Tan],Infinity]
Out[180]= {Tan[q]}

预期它可以与大多数格式为fun[expr_,rule_,otherArgs___]的函数一起使用。特别是,这些包括Cases,DeleteCases, Replace, ReplaceAll,ReplaceRepeated。我没有概括规则列表,但这应该很容易做到。在某些微妙的情况下,例如在某些情况下,它可能无法正常工作。具有非平凡的头和头上的图案匹配。

关于wolfram-mathematica - 仅匹配某些元素的 "children"的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6451802/

相关文章:

wolfram-mathematica - 如何摆脱分子中的分母和数学中的分母

graphics - 在 Mathematica 中排列和显示网格的各个部分

wolfram-mathematica - 在函数中使用剪贴板

c# - 应用于 .NET : avoid type checking with pattern matching involves a performance issue? 的清洁代码

java - 应该在 java.util.Scanner 中使用什么模式来获取下一个字符串标识符?

wolfram-mathematica - 格式化 mathematica 输出结果列表

wolfram-mathematica - 如何减少Mathematica中自变量的数量

generics - 我可以创建与实现模式的泛型类型的匹配吗?

java - 什么正则表达式可以匹配相似的字符?

java - 如何为汉字编写正则表达式