为了账号安全,请及时绑定邮箱和手机立即绑定

替换除最后一次出现以外的所有字符

替换除最后一次出现以外的所有字符

Go
梦里花落0921 2023-02-06 18:57:02
我正在对这样的字符串执行字符替换:result = strings.ReplaceAll(result, ".", "_")这按预期工作,但我想保留最后一次出现的.而不是替换它,只是让它独自一人。有没有一种奇特的方法可以做到这一点?
查看完整描述

4 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

分成[]string, 然后Join除最后 ;)


func ReplaceAllButLast(data, old, new string) string {

    split := strings.Split(data, old)

    if len(split) < 3 {

        return data

    }

    last := len(split) - 1

    return strings.Join(split[:last], new) + old + split[last]

}

https://go.dev/play/p/j8JJP-p_Abk


func main() {

    println(ReplaceAllButLast("a", ".", "_"))

    println(ReplaceAllButLast("a.b", ".", "_"))

    println(ReplaceAllButLast("a.b.c", ".", "_"))

    println(ReplaceAllButLast("a.b.c.d", ".", "_"))

}

生产的


a

a.b

a_b.c

a_b_c.d

更新


那是个玩笑,只是为了花哨


最好的方法是计算匹配次数并替换Count()-1,第二个ReplaceAll直到最后一个匹配位置并使用Join最慢


func ReplaceAllButLast_Count(data, old, new string) string {

    cnt := strings.Count(data, old)

    if cnt < 2 {

        return data

    }

    return strings.Replace(data, old, new, cnt-1)

}


func ReplaceAllButLast_Replace(data, old, new string) string {

    idx := strings.LastIndex(data, old)

    if idx <= 0 {

        return data

    }


    return strings.ReplaceAll(data[:idx], old, new) + data[idx:]

}


func ReplaceAllButLast_Join(data, old, new string) string {

    split := strings.Split(data, old)

    if len(split) < 3 {

        return data

    }

    last := len(split) - 1

    return strings.Join(split[:last], new) + old + split[last]

}

基准使用a.b.c.d -> a_b_c.d


goos: windows

goarch: amd64

pkg: example.org

cpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz

Benchmark_Count-8       16375098            70.05 ns/op        8 B/op          1 allocs/op

Benchmark_Replace-8     11213830           108.5 ns/op        16 B/op          2 allocs/op

Benchmark_Slice-8        5460445           217.6 ns/op        80 B/op          3 allocs/op



查看完整回答
反对 回复 2023-02-06
?
慕勒3428872

TA贡献1848条经验 获得超5个赞

处理这个问题最明显的方法是结合Replaceand Count:


func ReplaceAllExceptLast(d string, o string, n string) string {

    strings.Replace(d, o, n, strings.Count(d, o) - 1)

}

但是,我认为这不是最佳解决方案。对我来说,最好的选择是这样做:


func ReplaceAllExceptLast(d string, o string, n string) string {

    ln := strings.LastIndex(d, o)

    if ln == -1 {

        return d

    }


    return strings.ReplaceAll(d[:ln], o, n) + d[ln:]

}

这是通过获取要替换的值的最后一次出现的索引,然后对字符串进行全部替换直到该点。例如:


println(ReplaceAllExceptLast("a", ".", "_"))

println(ReplaceAllExceptLast("a.b", ".", "_"))

println(ReplaceAllExceptLast("a.b.c", ".", "_"))

println(ReplaceAllExceptLast("a.b.c.d", ".", "_"))

将产生:


a

a.b

a_b.c

a_b_c.d


查看完整回答
反对 回复 2023-02-06
?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

我想到的第一个解决方案是Positive Lookahead正则表达式

[.](?=.*[.])

但是, Golang re2(?=re)不支持


我们可以用Non-capturing group这种方式来实现

  • 首先使用 (?:[.])( Match a single character present in the list below [.]) 来查找所有点索引。

  • 然后用'_'代替最后一个点。

样本

func replaceStringByIndex(str string, replacement string, index int) string {

    return str[:index] + replacement + str[index+1:]

}


func replaceDotIgnoreLast(str string, replacement string) string {

    pattern, err := regexp.Compile("(?:[.])")

    if err != nil {

        return ""

    }


    submatches := pattern.FindAllStringSubmatchIndex(str, -1)

    for _, submatch := range submatches[:len(submatches)-1] {

        str = replaceStringByIndex(str, replacement, submatch[0])

    }


    return str

}


func main() {

    str := "1.2"

    fmt.Println(replaceDotIgnoreLast(str, "_"))

    str = "1.2.3"

    fmt.Println(replaceDotIgnoreLast(str, "_"))

    str = "1.2.3.4"

    fmt.Println(replaceDotIgnoreLast(str, "_"))

}

结果


1.2

1_2.3

1_2_3.4


查看完整回答
反对 回复 2023-02-06
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

  1. 使用strings.Count来计算要替换的字符串出现的次数

  2. 将 count-1 传递给strings.Replace以省略最后一次出现

func ReplaceAllButLast(input string, find string, replace string) string {
    occurrencesCount := strings.Count(input, find)
        return strings.Replace(input, find, replace, occurrencesCount-1)
}



查看完整回答
反对 回复 2023-02-06
  • 4 回答
  • 0 关注
  • 107 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信