【问题标题】:Stream or Iterator to generate all strings that match a regular expression?Stream 或 Iterator 生成与正则表达式匹配的所有字符串?
【发布时间】:2012-02-02 12:57:24
【问题描述】:

这是my previous question的后续行动。

假设我想生成匹配给定(简化)正则表达式的 all 字符串。

这只是一个编码练习,我没有任何额外的要求(例如实际生成了多少个字符串)。所以主要要求是生成漂亮、干净、简单的代码。

我考虑过使用Stream,但在阅读this question 之后,我正在考虑使用Iterator。你会用什么?

【问题讨论】:

  • 在您输入* 的那一刻,您将产生无限(而且非常无聊)的输出。
  • 好的,假设它是一个非常受限的语法(absequencealternatezero or more
  • 你仍然可以在正则表达式中使用*,你只需要一个更复杂的算法,不会卡在重复添加字符上。例如,如果你有[a-z]*[ab],你可以生成a b aa ab ba bb ca cb ... za zb aaa aab...

标签: regex algorithm scala stream iterator


【解决方案1】:

这个问题的解决方案要求的代码太多,无法在这里回答,但大纲如下。

首先,您要解析正则表达式——例如,您可以为此查看解析器组合器。然后,您将拥有一个评估树,例如,

List(
  Constant("abc"),
  ZeroOrOne(Constant("d")),
  Constant("efg"),
  OneOf(Constant("h"),List(Constant("ij"),ZeroOrOne(Constant("klmnop")))),
  Constant("qrs"),
  AnyChar()
)

除了将这个表达式树作为匹配器运行,您可以通过在每个术语上定义一个生成方法来将其作为生成器运行。对于某些术语(例如ZeroOrOne(Constant("d"))),会有多个选项,因此您可以定义一个迭代器。一种方法是在每个术语中存储内部状态并传入“提前”标志或“重置”标志。在“重置”时,生成器返回第一个可能的匹配项(例如"");提前,它会转到下一个并返回(例如"d"),同时消耗提前标志(让其余的在没有标志的情况下进行评估)。如果没有更多项目,它会为自身内部的所有内容生成重置,并为下一个项目保留前进标志。您从重置运行开始;在每次迭代中,您都会先进行一次,然后在再次取出时停止。

当然,像"d+" 这样的一些正则表达式结构可以产生无限多的值,所以你可能希望以某种方式限制它们(或者在某些时候返回,例如d...d 表示“很多”);和其他有很多可能的值(例如,. 匹配任何字符,但你真的想要所有 64k 字符,还是有许多 unicode 代码点?),你可能希望也限制这些。

无论如何,这虽然很耗时,但会生成一个工作的生成器。而且,顺便说一句,如果您为解析树的每一部分编写一个匹配例程,您还将拥有一个有效的正则表达式匹配器。

【讨论】:

  • 谢谢。您会使用streamiterator 还是不使用它们来实现“单词生成器”?
  • 我可能一个都不用,但可以很容易地用IteratorStream 包装。
  • 如果他把问题看成图的生成,那么广度优先的方法可以生成无限的序列而不限制重复次数。
  • @DanielC.Sobral - 确实如此,尽管我正在考虑嵌套组的任意复杂情况,虽然您可以提出对角化策略,但不一定会产生有趣的部分在被无聊的东西淹没之前,深入了解正则表达式。在简单的情况下,我同意——这可能是一个好方法。
猜你喜欢
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多