4 回答

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

TA貢獻1848條經驗 獲得超6個贊
處理這個問題最明顯的方法是結合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

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

TA貢獻1852條經驗 獲得超1個贊
使用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) }
- 4 回答
- 0 關注
- 169 瀏覽
添加回答
舉報