将组合器解析器的列表/序列转换为单个解析器

2024-01-16

我有一个值列表,可以从中构造一个解析器列表,这些解析器通过映射依赖于这些值(请参见示例)。然后我想做的就是通过串联将解析器列表变成单个解析器。

一种可能性是使用foldLeft and ~:

parsers.foldLeft(success(Nil)){case (ps,p) => rs ~ p ^^ {case xs ~ x => x ::xs}} ^^ (_.reverse)

这有效率吗?

我不知道组合器解析器是如何工作的;是否会有一个深度为列表长度的调用堆栈?因此,对于很长的连接,我可能会遇到 SO 错误吗?

更好的方法

有没有更易读的不同方式?

Example

假设您有一个包含两行的文件。第一行包含n个整数x_1到x_n。第二行包含 x_1 + x_2 + ... x_n 属于根据第一行的组的整数。我想从第一行获取整数序列并创建 n 个解析器 p_1 到 p_n,其中 p_i 解析 x_i 整数。

假设我有整数列表l = List(1,2,3)从第一行开始。对于每个整数n我创建了一个解析器来解析n整数:parsers = l.map(repN(_,integer)).


您所描述的内容(以及您在实施中或多或少重新发明的内容)foldLeft and ~)本质上是 Haskell 的sequence http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Monad.html对于单子(实际上你只需要一个应用函子,但这与这里无关)。sequence接受一元值列表并返回一元值列表。Parser是一个单子,所以sequence for Parser会改变一个List[Parser[A]] into a Parser[List[A]].

Scalaz http://code.google.com/p/scalaz/给你sequence,但我不知道是否有一个很好的方法来获得必要的Applicative实例为Parser。幸运的是,你可以很容易地推出自己的(我直接翻译哈斯克尔定义 http://haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Monad.html#sequence):

import scala.util.parsing.combinator._

object parser extends RegexParsers {
  val integer = """\d+""".r

  val counts = List(1, 2, 3)
  val parsers = counts.map(repN(_, integer))

  val line = parsers.foldRight(success(Nil: List[List[String]])) {
    (m, n) => for { x <- m ; xs <- n } yield (x :: xs)
  }

  def apply(s: String) = parseAll(line, s)
}

这给了我们List(List(1), List(2, 3), List(4, 5, 6)) for parser("1 2 3 4 5 6"), 如预期的。

(请注意,我正在使用RegexParsers这里作为一个方便的完整示例,但该方法更通用。)

如果我们脱糖的话,发生的事情可能会更清楚一些for理解:

val line = parsers.foldRight(success(Nil: List[List[String]])) {
  (current, acc) => current.flatMap(x => acc.map(x :: _))
}

我们可以写flatMap as into and map as ^^:

val line = parsers.foldRight(success(Nil: List[List[String]])) {
  (current, acc) => current into (x => acc ^^ (x :: _))
}

这与您的公式并不太远,只是我们使用的是正确的折叠而不是反转,并且没有建立和分解~s.


关于效率:我们的两种实现都会导致令人不愉快的调用堆栈。根据我的经验,这只是 Scala 解析器组合器的一个事实。去引用另一个堆栈溢出答案 https://stackoverflow.com/questions/6011141/scala-parser-combinators-vs-antlr-java-generated-parser/6011722#6011722, 例如:

Scala 的解析器组合器效率不高。他们不是 设计为。它们适合完成相对较小的任务 小投入。

My sequence-y 方法解决了问题的“更具可读性”部分,并且几乎肯定是使用 Scala 解析器组合器解决问题的最简洁方法。它比您的实施效率稍高,并且对于几千个左右的组来说应该没问题。如果你需要处理的事情不止于此,你就必须把目光投向外部scala.util.parsing.combinator。我会推荐如下内容:

def parse(counts: Seq[Int], input: String): Option[Seq[Seq[Int]]] = {
  val parsed = try {
    Some(input.split(" ").map(_.toInt))
  } catch {
    case _ : java.lang.NumberFormatException => None
  }

  parsed.flatMap { ints =>
    if (ints.length != counts.sum) None
    else Some(counts.foldLeft((Seq.empty[Seq[Int]], ints)) {
      case ((collected, remaining), count) => {
        val (m, n) = remaining.splitAt(count)
        (m.toSeq +: collected, n)
      }
    }._1.reverse)
  }
}

不能保证,但在我的系统上,它不会在包含 100k 整数组的行上溢出。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将组合器解析器的列表/序列转换为单个解析器 的相关文章

  • Scala:尝试 .getOrElse 与 if/else

    我是一名相当新的 Scala 开发人员 我是一名经验丰富的 Java 开发人员 到目前为止 我一直很喜欢 Scala 的简单性 我真的很喜欢函数式结构 而且它们常常迫使你编写更简洁的代码 然而最近我注意到 由于舒适性和简单性 我最终使用了在
  • Scala - Java = ? (或者 Clojure - Java = ?)

    开发人员可以在不懂 Java 的情况下使用 Scala 吗 开发人员可以在不懂 Java 的情况下使用 Clojure 吗 注意 例如 我是一名 C 开发人员 我在不了解任何 VB 的情况下使用 NET 当然 WF 4 0 使用 VB 进行
  • .java 和 .scala 类之间是否可能存在循环依赖?

    假设我在 java 文件中定义了类 A 在 scala 文件中定义了类 B A 类使用 B 类 B 类使用 A 类 如果我使用 java 编译器 则会出现编译错误 因为 B 类尚未编译 如果我使用scala编译器A类将找不到 有没有可以同时
  • Scala repl 抛出错误

    当我打字时scala在终端上启动 repl 它会抛出此错误 scala gt init error error while loading AnnotatedElement class file usr lib jvm java 8 ora
  • 什么样的函数被认为是“可组合的”?

    维基百科文章函数组合 计算机科学 https en wikipedia org wiki Function composition computer science says 就像数学中通常的函数组合一样 每个函数的结果作为下一个函数的参数
  • Spark - scala - 如何检查配置单元中是否存在表

    我必须使用 Spark 1 6 2 scala 检查配置单元中是否存在表 如果没有 我必须创建一个空数据框并将其保存为配置单元表 如果存在 则覆盖现有表 我需要一个返回布尔值的函数 基于该函数我可以做出上述决定 是否创建新表或覆盖现有表 1
  • “函数是第一等值”这到底是什么意思?

    有人可以用一些很好的例子清楚地解释它吗 在解释函数式编程时 我在 Scala 中遇到了这句话 一流 并不是一个正式定义的概念 但它通常意味着一个实体具有三个属性 有可能used 不受限制 只要 普通 值可以 即从函数传递和返回 放入容器等
  • 如何设计具有相互依赖的测试的 Specs2 数据库测试?

    有没有一些首选的方法来设计Specs2 http etorreborre github com specs2 测试 有很多测试取决于之前测试的结果 下面 您将找到我当前的测试套件 我不喜欢var位于测试片段之间 不过 它们是 需要的 因为某
  • Scala 中奇怪的类型不匹配

    我希望这个问题还没有在其他地方得到解答 在这里没有找到答案 在我的本地化系统中 我有一个名为 Language 的类 class Language val name String dict HashMap String String def
  • 如何从字符串列中提取数字?

    我的要求是从列中的评论列中检索订单号comment并且总是开始于R 订单号应作为新列添加到表中 输入数据 code id mode location status comment AS SD 101 Airways hyderabad D
  • IntelliJ IDEA 13:新的 Scala SBT 项目尚未生成 src 目录结构

    我按照 Jetbrains 网站上的入门视频设置 IntelliJ IDEA 13 1 Community Edition 以与 Scala 配合使用 Scala 插件 v0 36 431 已安装 当我使用向导创建一个新的 Scala SB
  • 如何将模型结果保存到文本文件?

    我正在尝试将从模型生成的频繁项集保存到文本文件中 该代码是 Spark ML 库中 FPGrowth 示例的示例 Using saveAsTextFile直接在模型上写入 RDD 位置而不是实际值 import org apache spa
  • 为什么 Scala 中的隐式类必须驻留在另一个特征/类/对象中?

    基于scala文档 http docs scala lang org overviews core implicit classes html http docs scala lang org overviews core implicit
  • 多个 scala 库导致 intellij 出错?

    我正在使用 intellij 14 和 scala 2 11 6 使用 homebrew 安装并使用符号链接 ln s usr local Cellar scala 2 11 6 libexec src usr local Cellar s
  • 具有两个通用参数的上下文边界

    在 Scala 中 我可以使用上下文边界 def sort T Ordered t Seq T 与以下意思相同 def sort T t Seq T implicit def Ordered T 如果我有一个带有两个泛型参数的类怎么办 IE
  • Akka Stream Graph 恢复问题

    我创建了一个图表来并行化具有相同输入的两个流 这些流产生 Future Option Entity 如果 flowA 失败 我想返回 Future None 但恢复似乎没有被调用 val graph Flow Input Future Op
  • 模拟 BlazeClientBuilder[IO] 以返回模拟客户端[IO]

    我正在使用BlazeClientBuilder IO resource方法得到Client IO 现在 我想模拟客户端进行单元测试 但不知道该怎么做 有没有一个好的方法来嘲笑这个 我会怎么做 class ExternalCall val r
  • andThen 类型不匹配的 Scala 链接函数

    我有一堆函数可以清理文本并将它们分成单词 最小的例子 val txt Mary had a little nlamb val stopwords Seq a def clean text String String text replace
  • scala中的反引号有什么用[重复]

    这个问题在这里已经有答案了 我在一本书上找到了以下代码 val list List 5 4 3 2 1 val result 0 list running total next element running total next elem
  • 解决“Show”类型类实例的隐式问题

    我正在努力使Gender实施Show类型类 scala gt trait Gender extends Show Gender defined trait Gender scala gt case object Male extends G

随机推荐

  • 通过 cron 发布到 Facebook

    两天来我一直在尝试将从 Twitter 搜索收集的消息自动发布到我的 Facebook 页面之一 即通过 cronjob twitter 部分运行得很好 但我怎么也无法让 Facebook 部分工作 问题是我的脚本可以工作 直到它不能工作
  • Visual Studio 代码未加载我的 python 解释器

    在这个项目中 我一直在使用我在 venv 中设置的 python 解释器 最近我更改了我的 python 解释器 我在用户设置中将其设置为默认解释器 例如 vs 文档vs code python 环境 https code visualst
  • EXC_BAD_ACCESS 使用 IBInspectable

    我正在尝试使用IBInspectable为我的视图添加边框 extension UIView private func getBorder integer Int gt UIRectEdge if integer 1 return top
  • 在 forEach 之后发送响应

    请注意 这不是两个类似标题问题的重复 这两个问题使用 Mongoose 并且答案仅适用于 Mongoose 查询 我有一个目录列表 每个目录都包含一个文件 我想返回一个 JSON 列表 其中包含每个文件的内容 我可以毫无问题地加载文件 但是
  • Python 检查值是否在字典列表中

    我有一个字典列表 例如 name Bernard age 7 name George age 4 name Reginald age 6 我想检查字符串值是否与列表中任何字典中的 名称 值相同 例如 Harold 将为 False 但 Ge
  • XMPP:检索 BOSH 会话 ID 和 RID

    请告诉我如何检索 SID 和 JID 我正在使用 Strope JS var conn new Strophe Connection bosh service 然而 conn sid or conn rid没有返回相同的数字 经过这个和那个
  • 尝试获取字段值时出现属性错误

    我正在使用 django 休息框架 并且我尝试使用的序列化器正在创建错误 我正在尝试做类似的事情https gist github com anonymous 7463dce5b0bfcf9b6767 https gist github c
  • 在不耗尽 RAM 的情况下使用并发 Future

    我正在做一些文件解析 这是一个 CPU 密集型任务 无论我向该进程放入多少文件 它使用的 RAM 都不会超过 50MB 该任务是可并行的 我已将其设置为使用下面的并发 future 将每个文件解析为单独的进程 from concurrent
  • 在Java中写入文本文件而不覆盖

    我正在尝试编写一种方法 如果 log txt 文件 尚不存在 则创建一个 log txt 文件 然后写入该文件 我遇到的问题是每次调用该方法时 它都会覆盖现有日志 如何更改方法 以便不覆盖数据而只更新文件 我的写入文件方法 File log
  • DataTable - 使可滚动,设置背景颜色并修复/冻结标题行和第一列

    我开始在 Flutter 中使用 webview 图表 表格进行开发 但是我遇到了一些表格问题 I use 数据表来表示表中的数据 有第一个问题 默认情况下 如果数据超出屏幕 则它不可滚动 所以我嵌入了一些小部件 即 SingleChild
  • 如何输入提示

    我如何输入提示来摆脱剩余的反射调用 def B amap D A i D B amap doubles aget A int i j doubles row 2 aget row int j 还剩下两个反射调用 但我不知道如何摆脱它们 您没
  • 使用 Alpha 通道绘制重叠的圆圈

    这个问题已经在这里得到了回答 重叠圆的组合面积 https stackoverflow com questions 1667310 combined area of overlapping circles 不过我的问题更具体 我在其他任意大
  • 不同格式的 SQL Server 日期时间比较

    我有一个 SQL 查询 我将在其中传递dd mm yyyy但SQL查询需要mm dd yyyy 我怎样才能启用此查询dd mm yyyy并根据正确的格式显示正确的结果 在 SQL Server 2008 中实现这一目标的最佳方法是什么 SE
  • realurl 生成没有 cHash 的条目

    我有一个 piBase 扩展 其中包含记录列表和详细信息页面 当首先调用列表时 一切都很好 realurl 版本2 0 15 TYPO3版本7 6 10 使用cHash参数创建详细信息页面的url 例如 cHash dc3409cee49f
  • Bootstrap 4.0 - 带图像+导航栏+全高正文的响应式标题

    我正在使用 bootstrap 4 构建一个响应式页面 其中有一个标题 标题部分 其中包含客户徽标 名称和导航栏的图像 所有这些元素都是响应式的 即图像根据屏幕尺寸缩小 导航栏在小屏幕上最小化 现在我想让身体也能做出反应 即 用内容填充屏幕
  • 多表触发器 SQL Server noob

    我有很多表都具有相同的 2 个日期时间列 lastModDate dateAdded 我想知道是否可以为这些表设置全局插入更新触发器来设置日期时间值 或者如果没有 有哪些方法 非常感谢任何指点 我同意没有这样的全局触发器 但是我们当然可以通
  • 如何将约束名称添加到已存在的约束中

    有没有办法为已经存在的约束命名 例如 create table employee emp id number 10 emp name varchar2 20 dept id number 10 foreign key dept id ref
  • Rails attr_accessible rspec 检查

    当我想测试属性是否为 不是时无障碍使用 RSpec 我这样做 class Foo attr accesible something else end describe Foo do it author should not be acces
  • 读取顺序文件 - 压缩文件与未压缩文件

    我正在寻找从磁盘读取顺序文件的最快方法 我在一些帖子中读到 如果我使用 lz4 等压缩文件 我可以获得比读取平面文件更好的性能 因为我将最大限度地减少 i o 操作 但是当我尝试这种方法时 扫描 lz4 压缩文件的性能比扫描平面文件差 我没
  • 将组合器解析器的列表/序列转换为单个解析器

    我有一个值列表 可以从中构造一个解析器列表 这些解析器通过映射依赖于这些值 请参见示例 然后我想做的就是通过串联将解析器列表变成单个解析器 一种可能性是使用foldLeft and parsers foldLeft success Nil