Mathematica中PatternTest的意外行为

12

我正在尝试通过解决一些玩具问题来理解Mathematica中的模式匹配思想。以下代码的行为与我的预期不符,我无法确定我的PatternTest理解有什么问题。

MatchQ[{2, 1, 2, 5}, {x__?(FromDigits[{#}] > 3 &), y__}]

我原以为这段代码可以检查列表{2,1,2,5}是否可被写成两个连续(非空)序列,使得从第一个序列得到的整数大于3。因为 {Sequence[2,1],Sequence[2,5]} 是将列表重写成满足 FromDigits[{2,1}] > 3 的一种方法,所以我期望代码返回 True。然而实际情况并非如此。

我的解析出了什么问题?

1个回答

14

PatternTest(也称为?)的文档说:

在形如__?test的形式中,对于由__匹配的序列中的每个元素,在应用测试时必须产生True

因此,您的代码将无法按照您的期望工作。

了解模式如何工作的好方法是使用ReplaceList。与您的代码相似的内容是

In[1]:= ReplaceList[{3, 4, 2, 1}, 
          {___, x__?(FromDigits[{##}] > 3 &), y___} :> {{x}, {y}}]

Out[1]= {{{4}, {2, 1}}}

然而,如果你使用条件 (/;)而不是模式测试,那么你可以得到你所寻求的行为。

In[2]:= ReplaceList[{3, 4, 2, 1}, 
          {___, x__, y___} :> {{x}, {y}} /; FromDigits[{x}] > 3]

Out[2]= {{{3, 4}, {2, 1}}, {{3, 4, 2}, {1}}, {{3, 4, 2, 1}, {}}, 
         {{4}, {2, 1}}, {{4, 2}, {1}}, {{4, 2, 1}, {}}, {{2, 1}, {}}}

@Leonid:拖延症的力量无所不及! - Simon
我认为那个回复是在我写评论的同时快速撰写的。 - Daniel Lichtblau
1
@Simon 非常感谢!我从你的回复中得到了很多提示:用 ## 代替 #,使用 ReplaceList 测试模式,以及 /; 和 __?test 的区别。 - Michael Wijaya
@nixeagle,偶尔你会发现一个20分钟内没有人回答的“简单”问题,比如这个,然后你需要抓住机会。 - rcollyer
@nixeagle 或者你可以使用这个工具:https://dev59.com/hWw15IYBdhLWcg3wmc8J - Sjoerd C. de Vries
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接