Golang中是否有类似Python的rsplit()函数?

Golang中是否有类似Python的rsplit()函数? 大家好,希望你们今天/今晚过得愉快。我正在尝试学习 Go 中 Split() 方法的工作原理,并且想知道 Go 中是否有类似 Python 中 rsplit() 的功能。

我一直在尝试的是获取用户输入,按空格分割,并将其存储到一个名为 ‘hey’ 的切片中,然后打印出来。我目前的代码如下:

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {

        text := scanner.Text()
        if text == "0" {
            break
        }

        hey := strings.Split(text, " ")
        fmt.Println(hey)
    }
}

我期望用户输入的形式是:

城市名称 经度 纬度

在一行内。例如,如果用户输入:

London 185 86

那么 hey 切片将是 {London 185 86},这符合我的预期。

但问题是当用户输入一个带有空格的城市名称时,例如“Buenos Aires”。那么用户输入将类似于“Buenos Aires 185 86”。

在这种情况下,我希望 hey 切片是 {Buenos Aires 185 86},在 Go 中有没有好的方法来实现这一点?在 Python 中可以使用 rsplit(" ", 2) 来完成,但我已经搜索过并阅读了文档,却找不到类似的方法。有人能帮我解决这个问题吗?


更多关于Golang中是否有类似Python的rsplit()函数?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

非常感谢您的友好回复!

更多关于Golang中是否有类似Python的rsplit()函数?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


由于城市名称可能包含多个单词,也许更好的方法是读取单词并检查每个单词的类型(字符串或数字),然后仅连接字符串……

这听起来是个好主意,但我该怎么做呢?

我可能会这样做:

	fields := strings.Fields("Buenos Aires 185 86")
	for len(fields) > 3 {
		fields[1] = fields[0] + " " + fields[1]
		fields = fields[1:]
	}

Playground

我脑海中快速闪过一个简单直接的解决方案,如下所示:

package main

import (
    "fmt"
    "strconv"
    "strings"
)

const data = "Buenos Aires 185 86"

func main() {

    var city string
    var long, lat int

    for i, fields := 0, strings.Fields(data); i < len(fields); i++ {
    	if _, err := strconv.Atoi(fields[i]); err != nil {
    		city = city + fields[i] + " "
    		continue
    	}
    	long, _ = strconv.Atoi(fields[i])
    	lat, _ = strconv.Atoi(fields[i+1])
    	city = city[:len(city)-1]
    	break
    }
	fmt.Printf("%s, [%d %d]\n", city, long, lat)
}

你也可以尝试一个更复杂的名称,例如 Edinburgh of the Seven Seas

在Go标准库中没有直接对应Python rsplit()的函数,但可以通过组合现有函数实现相同功能。以下是几种解决方案:

方案1:使用strings.LastIndex()手动分割

func rsplit(s, sep string, n int) []string {
    result := make([]string, 0, n+1)
    for i := 0; i < n; i++ {
        idx := strings.LastIndex(s, sep)
        if idx == -1 {
            break
        }
        result = append([]string{s[idx+len(sep):]}, result...)
        s = s[:idx]
    }
    result = append([]string{s}, result...)
    return result
}

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        text := scanner.Text()
        if text == "0" {
            break
        }
        
        // 从右侧分割2次(对应Python的rsplit(" ", 2))
        hey := rsplit(text, " ", 2)
        fmt.Println(hey)
    }
}

方案2:使用strings.Fields()和手动重组

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        text := scanner.Text()
        if text == "0" {
            break
        }
        
        // 分割所有字段
        fields := strings.Fields(text)
        if len(fields) >= 3 {
            // 最后两个元素是经度和纬度
            lat := fields[len(fields)-1]
            lon := fields[len(fields)-2]
            // 剩余部分合并为城市名
            city := strings.Join(fields[:len(fields)-2], " ")
            
            hey := []string{city, lon, lat}
            fmt.Println(hey)
        } else {
            fmt.Println(fields)
        }
    }
}

方案3:使用正则表达式

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    // 匹配:城市名(可能包含空格) + 空格 + 数字 + 空格 + 数字
    re := regexp.MustCompile(`^(.+?)\s+(\d+)\s+(\d+)$`)
    
    for scanner.Scan() {
        text := scanner.Text()
        if text == "0" {
            break
        }
        
        matches := re.FindStringSubmatch(text)
        if matches != nil {
            hey := []string{matches[1], matches[2], matches[3]}
            fmt.Println(hey)
        } else {
            fmt.Println("格式错误")
        }
    }
}

方案4:使用strings.SplitN()配合反转(最接近Python rsplit逻辑)

func reverseSplit(s, sep string, n int) []string {
    // 先分割成多个部分
    parts := strings.Split(s, sep)
    if len(parts) <= n {
        return parts
    }
    
    // 从右侧开始分组
    result := make([]string, n+1)
    // 最后n个元素单独放置
    for i := 0; i < n; i++ {
        result[n-i] = parts[len(parts)-1-i]
    }
    // 剩余部分合并为第一个元素
    result[0] = strings.Join(parts[:len(parts)-n], sep)
    
    return result
}

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        text := scanner.Text()
        if text == "0" {
            break
        }
        
        hey := reverseSplit(text, " ", 2)
        fmt.Println(hey)
    }
}

对于你的具体用例(城市名 经度 纬度),方案2最简单实用。如果需要更通用的rsplit功能,方案1或方案4提供了可重用的函数。

回到顶部