-
SMILET
分成[]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_Abkfunc main() { println(ReplaceAllButLast("a", ".", "_")) println(ReplaceAllButLast("a.b", ".", "_")) println(ReplaceAllButLast("a.b.c", ".", "_")) println(ReplaceAllButLast("a.b.c.d", ".", "_"))}生产的aa.ba_b.ca_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.dgoos: windowsgoarch: amd64pkg: example.orgcpu: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHzBenchmark_Count-8 16375098 70.05 ns/op 8 B/op 1 allocs/opBenchmark_Replace-8 11213830 108.5 ns/op 16 B/op 2 allocs/opBenchmark_Slice-8 5460445 217.6 ns/op 80 B/op 3 allocs/op
-
慕勒3428872
处理这个问题最明显的方法是结合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", ".", "_"))将产生:aa.ba_b.ca_b_c.d
-
牛魔王的故事
我想到的第一个解决方案是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.21_2.31_2_3.4
-
小怪兽爱吃肉
使用strings.Count来计算要替换的字符串出现的次数将 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)
}