在Go中分割字符串并将子字符串转换为整数

8
我有一个变量,内容类似于1,2,3。实际上这是三个值,我想将它们分别赋值给三个变量,分别为v1v2v3(但不要用数组)。
目前,我是这样做的:
tmp := strings.Split(*w, ",")
sw, _ := strconv.Atoi(tmp[0])
rw, _ := strconv.Atoi(tmp[1])
pw, _ := strconv.Atoi(tmp[2])

这段代码是可行的,虽然它很重复,并且在Go中不够自然。

有没有更简洁的方法来解决这个问题呢?


1
这差不多就是你该怎么做的,说实话。话虽如此,如果你将其作为逗号分隔列表输入,为什么不将其处理为整数切片呢?你可以用循环转换它。似乎是一个代码气味问题。另外,不要忽略从Aoti返回的错误(尽管您可能只是为了压缩示例代码而这样做)。 - Kaedys
如果您想要将结果存储在本地变量 swrwpw 中,那么这就是实现的方法。如果您想要一个值的切片,代码会更简洁,但您将无法获得具有单独值的本地变量集合。 - Adrian
@Kaedys 是的,我只是为了简短而忽略了它。我正在编写一个程序,接口是按照这种方式指定的,超出了范围,所以我必须处理这个格式。sw、rw、pw有特殊的含义,将它们分开更有意义。 - Karol Babioch
3个回答

13
从具有特定格式的字符串中解析数据,并将解析后的值存储到变量中,是一个完美的任务,并且可以使用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)

我们在输入中添加一个特殊的字符 unlikely,并期望在格式化字符串中出现该特殊字符。尝试解析无效输入(如 "1,2,3,""1,2,3,4")将导致出现错误,例如:
3 input does not match format 1 2 3

Go Playground上尝试一下。


似乎这是最干净的解决方案,尽管它非常宽松。例如 1,2,3,41,2,3, 也会被识别。 - Karol Babioch
@KarolBabioch 是的,这可能是一个问题。如果你想要严格一些,可以看一下编辑后的答案。 - icza

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


不,这里不能使用切片。 - Karol Babioch

0
最好的选项是使用地图:
V = make(map[int]int)

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

1
或者一个切片。由于map[int]int在功能上与切片完全相同,只是效率更低。 - Kaedys
此外,代码无效,并将映射的每个元素设置为其键,这似乎不是所需的结果。 - Adrian
@Adrian,代码没有无效 :) - 这是一个处理这种值的示例。 - Eugene Lisitsky
再次强调,这两个版本都是示例,第一个展示了原则,第二个展示了用法。我已经进行了编辑,以便人们可以轻松理解。 - Eugene Lisitsky
我明确地询问了如何在不使用切片的情况下完成这个操作。;) - Karol Babioch
好的)我建议考虑使用映射解决方案,因为当参数数量增加并且保持语义时,它们会非常有用。如果像map[string]int这样使用,就像V["sw"]一样。 - Eugene Lisitsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接