首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >延迟读取球拍中的自定义类型

延迟读取球拍中的自定义类型
EN

Stack Overflow用户
提问于 2015-01-09 15:32:51
回答 2查看 217关注 0票数 1

我对Racket还不熟悉,我正试图编写一个函数来读取文件的行,将每一行解析为struct,并返回数据类型的惰性序列。下面是我输入格式的一个简单示例(一个带有行和列名的矩阵)。我的实际输入格式还包括一个标题行,我在这里省略了它,并且包含非常大的文件,这就是我需要懒惰的原因。

R1 1.0 2.3 1.2 R2 1.2 3.1 3.4

以下是我的最新尝试:

代码语言:javascript
复制
(struct row (key data))

(define (read-matrix in)
  (for [(line (in-lines in))]
    (let ([fields (string-split line "\t")]
      (row (first fields) (list->vector (map string->number (rest fields))))
      )))

我还尝试过许多其他方法,包括使用call-with-input-file。我对上述方法的问题是,如果我使用#lang racket,它不是懒惰的,使用#lang lazy string-split也没有定义。我应该补充一点,在我的用例中,我想要的语义是在整个序列被消耗时关闭端口,因为我可以保证整个序列将被消耗,或者程序将终止。

那么,我走的路对吗?我应该采取什么方法来解决这个问题?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-09 19:25:15

我把这个答案写得太离谱了,回来后发现你已经回答了。我无论如何都会发帖,以防细节对任何人有帮助。

如果您真的需要#lang lazy,并且想使用string-split,我认为您可以简单地使用(require racket/string)来使用它吗?

我不太明白你所说的“懒惰”是什么意思。如果您担心的话,使用in-lines不会将整个文件吸进内存中。它将一次一行地处理事物。

您可以做的一件事是定义一个助手函数,该函数处理行的读取和解析、检查eof并自动关闭输入端口:

代码语言:javascript
复制
(struct row (key data)
        #:transparent)

;; Example couple lines of input to use below.
(define text "R1 1.0 2.3 1.2\nR2 1.2 3.1 3.4")

;; read-matrix-row : input-port? -> (or/c eof row?)
;;
;; Given an input port, try to read another row.
(define (read-matrix-row in)
  (match (read-line in)
    [(? eof-object?)
     (close-input-port in)
     eof]
    [line (match (string-split line " ")
            [(cons key data)
             (row key (list->vector (map string->number data)))])]))

您可以通过多种方式使用此函数。一种方法是使用in-producer

代码语言:javascript
复制
;; Example use with in-producer:
(let ([in (open-input-string text)])
  (for/list ([x (in-producer read-matrix-row eof in)])
    x))
;; => (list (row "R1" '#(1.0 2.3 1.2))
;;          (row "R2" '#(1.2 3.1 3.4)))

该示例使用for/list生成list。当然,如果您有一个巨大的输入文件,这将产生一个巨大的list。但是您可以一个一个地显示它们,也可以一个一个地将它们写入文件或数据库中:

代码语言:javascript
复制
;; Example use, displaying one by one.
(let ([in (open-input-string text)])
  (for ([x (in-producer read-matrix-row eof in)])
    (displayln x))) ;or write to some file, for example

如果您更喜欢stream接口,那么可以很容易地从任何序列创建一个流,包括“interface”:

代码语言:javascript
复制
;; If you prefer a stream interface, we can use sequence->stream to
;; transform the producer sequence into a stream:
(define (matrix-row-stream in)
  (sequence->stream (in-producer read-matrix-row eof in)))

;; Example interactive use of the stream
(define stm (matrix-row-stream (open-input-string text)))
(stream-empty? stm)                     ;#f
(stream-first stm)                      ;(row "R1" '#(1.0 2.3 1.2))
(stream-empty? (stream-rest stm))       ;#f
(stream-first (stream-rest stm))        ;(row "R2" '#(1.2 3.1 3.4))
(stream-empty? (stream-rest (stream-rest stm))) ;#t
票数 1
EN

Stack Overflow用户

发布于 2015-01-09 16:04:37

尝试使用SRFI-13中的函数,这是一个字符串操作库,也可在#lang lazy中使用。

代码语言:javascript
复制
(require srfi/13)

然后这样做:

代码语言:javascript
复制
[fields (string-tokenize line)]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27863968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档