【问题标题】:Split string and convert the substrings to integers in Go在 Go 中拆分字符串并将子字符串转换为整数
【发布时间】:2018-04-18 20:55:56
【问题描述】:

我有一个包含1,2,3 之类的变量。这实际上是三个值,我想将它们包含在三个变量中,称为 v1、v2、v3(但 不是 在数组中)。

现在我正在通过以下方式执行此操作:

tmp := strings.Split(*w, ",")
sw, _ := strconv.Atoi(tmp[0])
rw, _ := strconv.Atoi(tmp[1])
pw, _ := strconv.Atoi(tmp[2])

这行得通,尽管它非常重复并且在 Go 中感觉不正确。

解决这个问题的更简洁的方法是什么?

【问题讨论】:

  • 你做的很好,tbh。也就是说,如果您将其作为逗号分隔的列表放入,为什么不将其作为整数切片来操作呢?你可以这样循环转换。似乎是代码异味问题。另外,不要忽略来自Aoti 的错误返回(尽管您可能刚刚这样做是为了压缩您的示例代码)。
  • 如果您想要局部变量sw、rw 和pw 中的结果,那么这就是执行此操作的方法。如果你想要一个值,代码会更简洁,但你不会让你的局部变量集具有单独的值。
  • @Kaedys 是的,我忽略它只是为了保持简短。我正在写一个程序,接口是用这种方式指定的,超出范围,所以我必须处理这种格式。 sw, rw, pw 有特殊含义,分开放置更有意义。

标签: string variables go split substring


【解决方案1】:

使用特定格式从string 中解析数据并将解析后的值存储到变量中是一项完美的任务,并且使用fmt.Sscanf() 可以轻松完成:

src := "1,2,3"

var a, b, c int

parsed, err := fmt.Sscanf(src, "%d,%d,%d", &a, &b, &c)
fmt.Println(parsed, err, a, b, c)

输出(在Go Playground上试试):

3 <nil> 1 2 3

严格要求

如上所述,这是非常宽松的,并且还将成功解析 "1,2,3," 和 "1,2,3,4" 输入。这可能是也可能不是问题(取决于您的情况)。如果你想让它变得严格,你可以应用这个小技巧:

var temp int
parsed, err := fmt.Sscanf(src+",1", "%d,%d,%d,%d", &a, &b, &c, &temp)

我们所做的是追加一个与输入匹配的数字。如果原始输入不以数字结尾(如"1,2,3,"),则解析将失败并出现非nil 错误,上例给出:

3 expected integer 1 2 3

在Go Playground 上试试。当然,它会继续解析“有效”输入而不会出现任何错误。

请注意,这仍然接受输入 "1,2,3,4"。我们可以将这个技巧“简化”为单个字符,我们不一定需要一个“目标”变量来存储它,它可以简单地由格式字符串指定,如下例所示:

parsed, err := fmt.Sscanf(src+"~", "%d,%d,%d~", &a, &b, &c)

我们在输入中附加一个特殊字符不太可能,并且我们希望格式字符串中出现这个特殊字符。尝试解析无效输入(例如"1,2,3," 或"1,2,3,4")将导致错误,例如:

3 input does not match format 1 2 3

在Go Playground 上试试。

【讨论】:

  • 似乎是最干净的解决方案,尽管它非常宽松。例如1,2,3,4 或1,2,3, 也会被识别。
  • @KarolBabioch 是的,这可能是也可能不是问题。如果您希望它严格,请参阅编辑后的答案。
【解决方案2】:

如果你对切片结果没问题,你可以用切片来做:

tmp := strings.Split(*w, ",")
values := make([]int, 0, len(tmp))
for _, raw := range tmp {
    v, err := strconv.Atoi(raw)
    if err != nil {
        log.Print(err)
        continue
    }
    values = append(values, v)
}

工作场所示例:https://play.golang.org/p/Y-QHmHP8Iy

【讨论】:

  • 不,这里不能选择切片。
【解决方案3】:

最好的选择是使用地图:

V = make(map[int]int)

// in cycle
for i :=1; i < 3; i ++ {
    V[i], _ = strconv.AtoI(tmp[i])
}

【讨论】:

  • 或者一片。由于 map[int]int 在功能上与切片相同,只是效率较低。
  • 同样代码无效,并且将地图的每个元素都设置为其键,这似乎不是我们想要的。
  • @Adrian,代码不是无效的 :) - 这是如何处理这些值的示例
  • 再次,两个版本都是例子,先说明原理。第二 - 用法。我进行了编辑,以便人们可以轻松理解。
  • 我明确询问如何在没有切片的情况下执行此操作;)。
猜你喜欢
  • 2020-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 2014-09-26
  • 2015-01-16
相关资源
最近更新 更多