【问题标题】:String splitting in the D languageD语言中的字符串拆分
【发布时间】:2013-07-25 09:37:03
【问题描述】:

我正在学习 D 并尝试拆分字符串:

   import std.stdio;
   import std.string;

    auto file = File(path, "r"); 
    foreach (line; file.byLine) {
           string[] parts = split(line);

编译失败:

Error: cannot implicitly convert expression (split(line)) of type char[][] to string[]

这行得通:

    auto file = File(path, "r"); 
    foreach (line; file.byLine) {
           char[][] parts = split(line);

但为什么我必须使用char[][]?据我了解文档,它说split 返回一个string[],我更喜欢。

【问题讨论】:

    标签: string split d


    【解决方案1】:

    使用split(line.idup)

    split 是一个模板函数,返回类型取决于它的参数。 file.byLine.front 返回一个 char[],出于性能原因,它也被重用。因此,如果您在当前循环迭代之后需要这些部件,则必须执行 dupidup,无论您需要什么。

    【讨论】:

    • idup 创建数组的不可变副本。因此,如果这很关键,您可以随时转换为不可变(如果需要)。例如:foreach (line; file.byLine.map!"cast(string)a") 和来自 std.algorithm 的 map。但是,请注意一般的不可变类型转换。
    • 你不应该抛弃不可变的,除非你真的知道你在做什么。这样做会颠覆类型系统,并可能导致意外行为。在此示例中,跨循环迭代存储字符串可能会导致它们“更改其值”,因为它们仍将指向 byLine 使用的同一个临时缓冲区。
    • 是的,但在一般情况下需要一个。 D 通常对原始字符串使用切片,因此如果没有 idup,您将不会进行任何分配,idup 会分配。但是,如果您需要跨循环迭代的字符串,则必须对其进行 dup/idup,因为 byLine 一遍又一遍地重用相同的缓冲区。如果您不需要所有拆分的部分,您可能只想复制您需要的部分。例如split(line).front.idup 如果你只需要第一部分。
    【解决方案2】:

    您可以使用std.stdio.lines。根据您键入foreach 循环变量的方式,它将为每次迭代分配一个新缓冲区或重用旧缓冲区。这样就可以保存.dup/.idup

    但是,选择哪种类型取决于您的用例(即您需要数据多长时间)。

    foreach(string line; lines(file)) { // new string every iteration }
    
    foreach(char[] line; lines(file)) { // reuse buffer } 
    

    使用ubyte 代替char 将禁用utf8 验证。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      相关资源
      最近更新 更多