【问题标题】:Can `strings.split` ignore empty tokens?`strings.split` 可以忽略空标记吗?
【发布时间】:2017-10-17 19:48:13
【问题描述】:

您能否演示一种使用strings.split 的有效方法,以使返回的切片中不包含空标记?

具体来说,下面的代码返回["a" "" "b" "c"],我想让它返回["a" "b" "c"]

fmt.Printf("%q\n", strings.Split("a,,b,c", ","))

https://play.golang.org/p/keaSjjSxgn

【问题讨论】:

  • 实现一个额外的功能,过滤掉你不想在那里的元素。实际上,这将是一个遍历字符串并检查它们的长度是否大于 0 的循环。由于缺乏泛型 - Go 不能有一个库函数可以完全为您执行此操作,因此一遍又一遍地重新实现它很有趣: -)
  • 实际上,如果您需要对不同的切片类型进行大量操作,请查看 sort 包的工作原理,不需要泛型。然而,对于字符串切片来说,编写一个通用的解决方案是大材小用。
  • @MiloChristiansen func Sort(data Interface) --- 这就是它的工作原理,使用接口。因此,您必须一遍又一遍地为每种数据类型实现接口。
  • 没错。 sort.Slice 更接近这个问题,而 IIRC 它使用反射。
  • "IIRC 它使用反射" --- yikes :-D

标签: go


【解决方案1】:

简答:strings.Split 做不到。

然而,Go 中有更多的函数可以分割字符串。值得注意的是,您可以使用strings.FieldsFunc 做您想做的事。这里的例子:

splitFn := func(c rune) bool {
        return c == ','
}
fmt.Printf("Fields are: %q\n", strings.FieldsFunc("a,,b,c", splitFn))

在操场上:https://play.golang.org/p/Lp1LsoIxAK

【讨论】:

  • 谢谢@T.Claverie,我觉得这绝对是惯用的做法。
  • 老实说,如果将这个函数命名为strings.SplitFunc 会更容易找到。很高兴它帮助了你:)
  • 有趣。事实证明,使用 strings.Split 然后遍历数组并删除空标记的性能大约提高了 30%。
  • 我查看了strings.Splitstrings.FieldsFunc 的源代码,发现FieldsFunc 进行了额外的迭代,因此我对两者都进行了测试。 FieldsFunc 的优势仍然在于可以使用更复杂的函数进行拆分。
【解决方案2】:

您可以从数组中过滤掉空元素,因此您可以将其作为第二步。

package main

import (
    "fmt"
    "strings"
)

func delete_empty (s []string) []string {
    var r []string
    for _, str := range s {
        if str != "" {
            r = append(r, str)
        }
    }
    return r
}

func main() {
    var arr = strings.Split("a,,b,c", ",");
    fmt.Printf("%q\n", delete_empty(arr));
}

更新Golang Playground

【讨论】:

  • 也可以预先分配r,因为您知道s 的最大潜在大小。
  • 如果你预先分配到s的长度,在有空字段要跳过的情况下你会过度分配。
  • @Adrian 必须评估几个 N-M ~bytes~ 符文“丢失”是否比额外的 M 分配更好。
  • @Niko 关心时 - 测量。
  • 我并没有声称有最优雅的答案。选择您认为可读性最强的。如果您发现最易读的代码存在性能问题,则优化起来会更容易。 “我们应该忘记小的效率,比如说大约 97% 的时间:过早的优化是万恶之源。但我们不应该放弃那关键的 3% 的机会。” - 克努特
【解决方案3】:

如果使用regexp 是可以接受的,您可以拆分为 1+ 个分隔符:

package main
import (
  "fmt"
  "regexp"
)

func main() {
  fmt.Printf("%q\n", regexp.MustCompile(",+").Split("a,,b,c", -1))
}

Playground link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-23
    • 2012-08-14
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2015-12-21
    相关资源
    最近更新 更多