【问题标题】:Is there finer granularity than LOAD/NEXT for reading structured data?读取结构化数据是否有比 LOAD/NEXT 更细的粒度?
【发布时间】:2010-11-04 03:37:43
【问题描述】:

想象一下,我有一个很长的 Rebol 格式数据文件,有一百万行,看起来像

REBOL []

[
    [employee name: {Tony Romero} salary: $10,203.04]
    [employee name: {Marcus "Marco" Marcami} salary: default]
    [employee name: {Serena Derella} salary: ($10,000 + $203.04)]

...

    [employee name: {Stacey Christie} salary: (10% * $102,030.40)]
]

如果封闭块不存在,我可以使用LOAD/NEXT 一次读取一个员工项目(而不是使用LOAD 将整个文件解析为结构化数据)。如果封闭块那里,有什么方法可以做类似的事情吗?

如果我想回到以前访问过的项目怎么办?会不会有“结构性寻求”?

是否有一种可行的数据库解决方案可以满足这种对 Rebol 结构化数据的需求,甚至可能允许随机访问插入?

【问题讨论】:

    标签: rebol seek structured-data


    【解决方案1】:

    我记得,是你证明了这在 PARSE 中应该是可行的? ;-)

    尽管如此,给您一个有用的答案:我为link text 编写的代码可以完全描述为解析(本质上)REBOL,而不是在需要其他东西时使用默认的 LOAD/NEXT。所以,看看,阅读文档,运行测试,写一些测试,如果你有更多问题,尽管问。

    【讨论】:

    • 为此使用 PARSE 非常有趣,您让我想知道 LOAD 在后台是如何工作的。当我看的时候我很惊讶它是一个夹层,它似乎读取了整个数据源(即使你只是在做 /NEXT!)不确定精确的细节,但是基于 PARSE 的 LOAD 夹层会有更多的增量阅读自然,并能够加载/返回?
    • 一个问题是 PARSE 不能在 PORT 上工作!目前,请参阅stackoverflow.com/questions/4127569/using-parse-on-a-port-value
    • 关于 LOAD/BACK - 这肯定是可以编写的,但需要权衡 - 这需要时间和精力,而且使用起来会非常出色。
    • PARSE 在端口上工作 - 我编写了“按部分”解析端口输入的代码,它作为开源协议 (BEER) 的一部分公开提供。但是,我认为不存在一个通用的解决方案——比如:缓冲区溢出、回溯、超时等,可能需要临时解决方案。
    【解决方案2】:

    如果您愿意稍微调整一下文件格式,使其成为每行一条记录、没有封闭块或 REBOL 标头的文件:

    employee-name: {Tony Romero} salary: $10203.04
    employee-name: {Marcus "Marco" Marcami} salary: 'default
    employee-name: {Serena Derella} salary: ($10000 + $203.04)
    employee-name: {Stacey Christie} salary: (10% * $102030.40)
    

    那么……

    data: read/lines %data-file.txt
    

    ....给你一个未加载的字符串块

    使用它们的一种方法是这样的:

    foreach record data [
        record: make object! load/all record
        probe record
    ]
    

    我还必须调整您的数据格式,以便 REBOL 轻松加载它:

    • 员工姓名而不是员工姓名
    • $10203.04 而不是 $10'203.04
    • 10% -- 仅适用于 REBOL3

    如果您不能像这样调整数据格式,您总是可以在 LOAD/ALL 之前对每个字符串进行一些编辑,以便对其进行规范化以用于 REBOL。

    【讨论】:

    【解决方案3】:

    Sunanda 的回答不好,因为您可以拥有多行数据! 你可以使用类似的东西:

    数据:{REBOL [] [ [员工姓名:{Tony Romero} 薪水:$10'203.04] [员工姓名:{Marcus "Marco" Marcami} 薪水:默认] [员工姓名:{Serena Derella} 薪水:($10,000 + $203.04)] ]} 除非所有 [ 设置 [值数据] 加载/下一个数据 值 = 'REBOL ][ print "不是 REBOL 数据文件!"停 ] 设置 [标题数据] 加载/下一个数据 print ["data-file-header:" 模具头] 数据:查找/尾数据#“[” 试图 [ ;您必须使用尝试,因为文件末尾至少会出现一个错误! ;** 语法错误:在块末尾缺少 [ 索引:复制 [] 尽管 [ 追加索引数据 set [loaded-row data] 加载/下一个数据 数据 ][ 探针加载行 ] ] 打印“完成” 删除后尾索引;删除最后一个错误位置 foreach data-at-pos 反向索引 [ 探测第一个加载/下一个数据在位置 ]

    所以输出将是:

    [员工姓名:“托尼·罗梅罗”薪水:$10203.04] [员工姓名:{Marcus "Marco" Marcami} 薪水:默认] [员工姓名:“Serena Derella”薪水:($10000.00 + $203.04)] 完毕 [员工姓名:“Serena Derella”薪水:($10000.00 + $203.04)] [员工姓名:{Marcus "Marco" Marcami} 薪水:默认] [员工姓名:“托尼·罗梅罗”薪水:$10203.04]

    【讨论】:

    • 如果你有大数据文件,你可以添加一些缓冲,不要一次读取所有文件。
    • btw .. 最好的解决方案是不要对数据使用封闭块:)
    • ATTEMPT 显然有点狡猾,因为它假定您的数据格式正确。但是,感谢您努力为问题中描述的特定场景编写代码以解决问题。我真的在思考一个可以在磁盘文件上工作的更通用的“搜索”,但后来意识到即使解析器能够加载/返回,那么无法进行修改也意味着它只会对非常有用狭隘的情况......
    • 如果您真的需要将数据存储在磁盘上并能够在不完全加载的情况下查找/修改它们,那么您不希望 REBOL 格式的数据,而是某种二进制形式的真实数据数据库做到了。
    • 另外我希望如果这是一个真实的例子,你应该很确定数据格式正确。您也可以随时添加错误类型检测。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2018-07-06
    • 2016-02-04
    相关资源
    最近更新 更多