for i, r := range s {
fmt.Printf("i%d r %c\n", i, r)
// every 3 i, do something
}
r[n:n+3]将最好的工作与一片符文。 The index will increase by one every rune, while it mightincrease by more than one for every bytein a slice of string: "世界": i would be 0 and 3: a character (rune) can be formed of multiple bytes. 例如,考虑s := "世a界世bcd界efg世":12符文。(参见play.golang.org) 如果你试图一个字节一个字节地解析它,你会错过(在一个简单的每3个字符拆分一次的实现中)一些“index modulo 3”(等于2、5、8和11),因为索引会增加超过这些值:
for i, r := range s {
res = res + string(r)
fmt.Printf("i %d r %c\n", i, r)
if i > 0 && (i+1)%3 == 0 {
fmt.Printf("=>(%d) '%v'\n", i, res)
res = ""
}
}
输出:
i 0 r 世
i 3 r a <== miss i==2
i 4 r 界
i 7 r 世 <== miss i==5
i 10 r b <== miss i==8
i 11 r c ===============> would print '世a界世bc', not exactly '3 chars'!
i 12 r d
i 13 r 界
i 16 r e <== miss i==14
i 17 r f ===============> would print 'd界ef'
i 18 r g
i 19 r 世 <== miss the rest of the string
for i, r := range a {
res = res + string(r)
fmt.Printf("i%d r %c\n", i, r)
if i > 0 && (i+1)%3 == 0 {
fmt.Printf("=>(%d) '%v'\n", i, res)
res = ""
}
}
输出:
i 0 r 世
i 1 r a
i 2 r 界 ===============> would print '世a界'
i 3 r 世
i 4 r b
i 5 r c ===============> would print '世bc'
i 6 r d
i 7 r 界
i 8 r e ===============> would print 'd界e'
i 9 r f
i10 r g
i11 r 世 ===============> would print 'fg世'
func ChunksSlower(s string, chunkSize int) []string {
if chunkSize >= len(s) {
return []string{s}
}
var chunks []string
chunk := make([]rune, chunkSize)
len := 0
for _, r := range s {
chunk[len] = r
len++
if len == chunkSize {
chunks = append(chunks, string(chunk))
len = 0
}
}
if len > 0 {
chunks = append(chunks, string(chunk[:len]))
}
return chunks
}
func SplitSubN(s string, n int) []string {
sub := ""
subs := []string{}
runes := bytes.Runes([]byte(s))
l := len(runes)
for i, r := range runes {
sub = sub + string(r)
if (i + 1) % n == 0 {
subs = append(subs, sub)
sub = ""
} else if (i + 1) == l {
subs = append(subs, sub)
}
}
return subs
}
// splitBy splits a string s by int n.
func splitBy(s string, n int) []string {
var ss []string
for i := 1; i < len(s); i++ {
if i%n == 0 {
ss = append(ss, s[:i])
s = s[i:]
i = 1
}
}
ss = append(ss, s)
return ss
}
// test
s := "helloworld"
ss := splitBy(s, 3)
fmt.Println(ss)
7条答案
按热度按时间ohtdti5x1#
确保将string转换为rune切片:参见“Slice string into letters”。
for
会自动将string
转换为rune
,因此在这种情况下,不需要额外的代码将string
转换为rune
。r[n:n+3]
将最好的工作与一片符文。The index will increase by one every rune, while it mightincrease by more than one for every bytein a slice of string: "世界":
i
would be 0 and 3: a character (rune) can be formed of multiple bytes.例如,考虑
s := "世a界世bcd界efg世"
:12符文。(参见play.golang.org)如果你试图一个字节一个字节地解析它,你会错过(在一个简单的每3个字符拆分一次的实现中)一些“index modulo 3”(等于2、5、8和11),因为索引会增加超过这些值:
输出:
但是如果你在rune(
a := []rune(s)
)上迭代,你会得到你所期望的,因为索引会一次增加一个rune,这样就可以很容易地聚合3个字符:输出:
eqqqjvef2#
这是另一个变体playground。它在速度和内存方面都比其他答案更有效。如果你想在这里运行基准测试,它们是benchmarks。一般来说,它比以前的版本快5倍,无论如何都是最快的答案。
请注意,在迭代字符串时,索引指向符文的第一个字节。符文需要1到4个字节。切片也将字符串视为字节数组。
先前较慢的算法
代码在这里playground。从字节到符文,然后再到字节的转换实际上需要很多时间。所以最好使用答案顶部的快速算法。
请注意,这两个算法以不同的方式处理无效的UTF-8字符。第一个算法将它们按原样处理,第二个算法将它们替换为
utf8.RuneError
符号('\uFFFD'
),该符号在UTF-8中具有以下十六进制表示:efbfbd
.xkftehaa3#
最近还需要一个函数来完成此操作,请参阅example usage here
toiithl64#
下面是另一个例子(你可以尝试here):
w3nuxt5m5#
使用regex的简单解决方案
re:= regexp.MustCompile(
(\S{3})
)x:= re.FindAllStringSubmatch(“HelloWorld”,-1)fmt.Println(x)https://play.golang.org/p/mfmaQlSRkHe
xu3bshqb6#
我尝试了3个版本来实现该函数,名为“splitByWidthMake”的函数最快。
这些函数忽略unicode而只忽略ascii代码。
ujv3wf0j7#
不是最有效的,将适用于大多数用例。
去Playground:https://play.golang.org/p/0JSqv3OMdCR