- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我听说迭代者很懒,但是他们到底有多懒呢?或者,是否可以将迭代器与后处理功能融合,从而不必构建中间数据结构?
例如,我可以在我的迭代器中构建一个 100 万个项目吗Stream[Option[String]]
来自 java.io.BufferedReader
,然后随后过滤掉 None
s,以组合的方式,不需要将整个 Stream 保存在内存中?并且同时保证我不炸堆?或类似的东西 - 它不必使用 Stream
.
我目前正在使用 Scalaz 6,但如果其他迭代实现能够以更好的方式做到这一点,我很想知道。
请提供完整的解决方案,包括关闭BufferedReader
并调用 unsafePerformIO
,如果适用的话。
最佳答案
这是一个使用 Scalaz 7 库的快速迭代示例,演示了您感兴趣的属性:常量内存和堆栈使用。
问题
首先假设我们有一个大文本文件,每行都有一串十进制数字,我们想要找到所有至少包含 20 个零的行。我们可以像这样生成一些样本数据:
val w = new java.io.PrintWriter("numbers.txt")
val r = new scala.util.Random(0)
(1 to 1000000).foreach(_ =>
w.println((1 to 100).map(_ => r.nextInt(10)).mkString)
)
w.close()
numbers.txt
的文件。 .让我们用
BufferedReader
打开它:
val reader = new java.io.BufferedReader(new java.io.FileReader("numbers.txt"))
import scalaz._, Scalaz._, effect.IO, iteratee.{ Iteratee => I }
IoExceptionOr
s 更改为
Option
s):
val enum = I.enumReader(reader).map(_.toOption)
val split = I.splitOn[Option[Char], List, IO](_.cata(_ != '\n', false))
splitOn
需要一个谓词来指定不拆分的位置让您感到困惑,您并不孤单。
split
是我们的第一个枚举示例。我们将继续将我们的枚举器包装在其中:
val lines = split.run(enum).map(_.sequence.map(_.mkString))
Option[String]
的枚举数s 在
IO
单子(monad)。
val pred = (_: String).count(_ == '0') >= 20
val filtered = I.filter[Option[String], IO](_.cata(pred, true)).run(lines)
val printAction = (I.putStrTo[Option[String]](System.out) &= filtered).run
unsafePerformIO
:
printAction.unsafePerformIO()
Some("0946943140969200621607610...")
s 慢慢滚动,而我们的内存使用量保持不变。它很慢,错误处理和输出有点笨拙,但我认为对于大约九行代码来说还不错。
foreach
-ish 用法。我们还可以创建一个更像折叠的迭代器——例如收集通过过滤器的元素并将它们返回到一个列表中。只需重复以上所有内容,直到
printAction
定义,然后改写:
val gatherAction = (I.consume[Option[String], IO, List] &= filtered).run
val xs: Option[List[String]] = gatherAction.unsafePerformIO().sequence
None
(如果是
IOException
沿途某处)或
Some
包含 1,943 个字符串的列表。
import java.io.{ BufferedReader, File, FileReader }
import scalaz._, Scalaz._, effect._, iteratee.{ Iteratee => I, _ }
def tryIO[A, B](action: IO[B]) = I.iterateeT[A, IO, Either[Throwable, B]](
action.catchLeft.map(
r => I.sdone(r, r.fold(_ => I.eofInput, _ => I.emptyInput))
)
)
def enumBuffered(r: => BufferedReader) =
new EnumeratorT[Either[Throwable, String], IO] {
lazy val reader = r
def apply[A] = (s: StepT[Either[Throwable, String], IO, A]) => s.mapCont(
k =>
tryIO(IO(reader.readLine())).flatMap {
case Right(null) => s.pointI
case Right(line) => k(I.elInput(Right(line))) >>== apply[A]
case e => k(I.elInput(e))
}
)
}
def enumFile(f: File): EnumeratorT[Either[Throwable, String], IO] =
new EnumeratorT[Either[Throwable, String], IO] {
def apply[A] = (s: StepT[Either[Throwable, String], IO, A]) => s.mapCont(
k =>
tryIO(IO(new BufferedReader(new FileReader(f)))).flatMap {
case Right(reader) => I.iterateeT(
enumBuffered(reader).apply(s).value.ensuring(IO(reader.close()))
)
case Left(e) => k(I.elInput(Left(e)))
}
)
}
val action = (
I.consume[Either[Throwable, String], IO, List] %=
I.filter(_.fold(_ => true, _.count(_ == '0') >= 20)) &=
enumFile(new File("numbers.txt"))
).run
关于scala - Scala 中使用惰性求值或融合的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13379219/
我输入了一个包含两个元素的 vector 。然后我将另一个元素 push_back 到它,并期望什么结果类型也是一个 vector 。但事实并非如此。 例子: typedef boost::fusio
首先让我先说,我以前在这里问过类似的问题,但从来没有得到解决我缺乏知识/问题的好答案。 首先,让我从一个分支策略提案开始。这就是我们的工作,我很高兴听到其他评论,以及为什么这很糟糕。但要明白它通常对我
所以我将一个带有 javascript 的字符串发送到 php 页面: if(cp.value!=''){ s+=cp.name +" LIKE '%"+ cp.value +"%'";
我有一个简单的问题,我该如何使用 which和 which.max同时。 我想选择最大值epnum为行 id == B13639J2 . 我需要检索 row number因为我需要对变量进行一些手动更
我想将带有 Groovy 脚本的文件上传到 Confluence。 As this Pythonscript example!我开始将代码翻译成 groovy, // Groovy def serve
我有一个融合 vector ,其元素具有多个不同类型的成员数据,我想创建一个新的融合 vector ,它将仅投影特定的数据成员。我已经对此进行了一段时间的研究,但没有任何进展。 #include #
我正在尝试使用 Python 的 xmlrpclib 创建一个新的页面以汇合。我已经知道如何更新现有页面的内容,但如何创建一个全新的页面? 我使用了以下脚本来更新内容: import xmlrpcli
我正在使用 Pow 在 Mac OS X 上为 Rack 应用程序提供服务。http://myapp.dev正确显示应用程序。在同一台机器上,我使用 VMware Fusion 运行 Windows
我检查了 Cassandra 和 Infinispan 的主要特性。它们似乎具有并提供非常相似的特性和功能: NoSQL 数据存储 坚持 去中心化 支持复制 可扩展性 容错 MapReduce 支持
我在Drupal 7网站中使用Search API和Elasticsearch Connector。我已经在AWS中托管了elasticsearch。搜索完美无误。但是我想像在Drupal.org搜索
我最近重新打开了几年前参与的一个项目。我写了一个小的 python 脚本来构建项目。我想将其移植到 CMake。 我遇到的问题是脚本使用了 pkg-config在 linux 上找到 fuse 头文件
我正在尝试访问 Yelp fusion API。我正在关注documentation并来到这段代码: const request = require('request'); // As you can
这是一个 vanilla Ubuntu 16.04 LTS,准确地说是基于 Xubuntu core。所以我需要自己安装包。除了 meld 之外,一切都很顺利,开始时,我会得到: (meld:4188
我正在尝试对惰性求值在 Java 流 API 中的应用形成一个简洁而连贯的理解。 这是我目前的理解: 元素仅在需要时才被消耗,即流是惰性的,中间操作也是惰性的,例如过滤器,仅在需要时进行过滤。 中间操
我使用 conluent jdbc-sink 将数据从 kafka 加载到 oracle。 但是我用数据编写了关于值(value)的模式。 我不想用数据编写模式,如何在 kafka 主题上编写模式,然
我在这里编写了一个 2D 融合套索代码。 [m n] = size(circle); cvx_begin variable theta(m, n); minimize( norm(ci
目前我正在开发一个使用 dx9 创建叠加层的应用程序。现在我遇到了一个问题,自从我将 Windows 10 升级到最新版本(Creators Update)后,它无法使用 alpha channel
我正在尝试编写类似 fiber 的代码,这样我就可以进入任务并从中退出。我试过的代码: class TaskActivity { CancellationTokenSource _m=new
我使用 NPM 在 React.js 中创建了一个前端。作为 IDE,我在这里使用 IntelliJ IDEA。该项目将使用我单独创建的 Spring Boot 编写的后端,也在 IntelliJ I
Cassandra 连接器在融合升级到 3.3.0 后失败。 Cassandra驱动的版本是3.3。堆栈如下。 [2017-09-14 08:56:28,123] ERROR java.lang.re
我是一名优秀的程序员,十分优秀!