我希望能够干净利落地剪切大于一定字符数的段落,而不会在中间剪切一个单词。
所以例如这个:
一个早已确定的事实是,读者会被 查看页面布局时的可读内容。要点 使用 Lorem Ipsum 是它或多或少具有 字母,而不是使用"此处内容,此处内容",使其成为 看起来像可读的英语。
应该变成:
一个早已确定的事实是,读者会被 可读内容...
这是我想出的功能:
func truncateText(s string, max int) string {
if len(s) > max {
r := 0
for i := range s {
r++
if r > max {
return s[:i]
}
}
}
return s
}
但它只是残酷地削减了文本。我想知道如何修改(或用更好的解决方案替换它(以便椭圆形剪切文本?
切片字符串可能会有问题,因为切片适用于字节,而不是符文。但是,范围适用于符文:
lastSpaceIx:=-1
len:=0
for i,r:=range str {
if unicode.IsSpace(r) {
lastSpaceIx=i
}
len++
if len>=max {
if lastSpaceIx!=-1 {
return str[:lastSpaceIx]+"..."
}
// If here, string is longer than max, but has no spaces
}
}
// If here, string is shorter than max
所写的范围是完全不必要的;就像现在一样,你的整个函数可能只是:
func truncateText(s string, max int) string {
return s[:max]
}
这很简单,甚至不应该是一个函数;但当然,它也会切断你说你不想要的单词。因此,您可以:
func truncateText(s string, max int) string {
if max > len(s) {
return s
}
return s[:strings.LastIndex(s[:max]," ")]
}
或者,如果您想使用多个字符作为单词边界而不仅仅是空格:
func truncateText(s string, max int) string {
if max > len(s) {
return s
}
return s[:strings.LastIndexAny(s[:max]," .,:;-")]
}
我改进了Burak的答案。此实现返回确切的输入字符串,如果len(text)=maxLen
而不是添加省略号,如果文本没有空格,它只是在maxLen
处执行硬截断。
func EllipticalTruncate(text string, maxLen int) string {
lastSpaceIx := maxLen
len := 0
for i, r := range text {
if unicode.IsSpace(r) {
lastSpaceIx = i
}
len++
if len > maxLen {
return text[:lastSpaceIx] + "..."
}
}
// If here, string is shorter or equal to maxLen
return text
}
测试用例
func TestEllipticalTruncate(t *testing.T) {
assert.Equal(t, "...", EllipticalTruncate("1 2 3", 0))
assert.Equal(t, "1...", EllipticalTruncate("1 2 3", 1))
assert.Equal(t, "1...", EllipticalTruncate("1 2 3", 2))
assert.Equal(t, "1 2...", EllipticalTruncate("1 2 3", 3))
assert.Equal(t, "1 2 3", EllipticalTruncate("1 2 3", 5))
}
以下解决方案避免了范围,但考虑了多字节符文:
func ellipsis(s string, maxLen int) string {
runes := []rune(s)
if len(runes) <= maxLen {
return s
}
if maxLen < 3 {
maxLen = 3
}
return string(runes[0:maxLen-3]) + "..."
}
请参阅 https://go.dev/play/p/ibj6aK7N0rc
我提供了非常简单的变体。
https://go.dev/play/p/Pbk5DchjReT
func ShortText(s string, i int) string {
if len(s) < i {
return s
}
if utf8.ValidString(s[:i]) {
return s[:i]
}
return s[:i+1]
}
要根据空格等进行拆分,您可以使用正则表达式:
func splitString(str string) []string {
re := regexp.MustCompile("[\s\n\t\r ]+") //split according to s, t, r, t and whitespace. Edit this regex for other 'conditions'
split := re.Split(str, -1)
return split
}
func main() {
var s = "It is a longnestablished fact that a readernwillnbe distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English."
var maxLen = 40
arr := splitString(s)
totalLen := 0
finalStr := ``
for _, each := range arr {
if (totalLen + len(each) > maxLen) {
fmt.Print(strings.TrimSpace(finalStr) + `...`)
break
}
totalLen += len(each)
finalStr += each + ` `
}
}
//旧 2
你可以做这种事情:将字符串分成切片并循环穿过切片,直到字符串的总长度高于允许的最大长度。
var s = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English."
var maxLen = 30
arr := strings.SplitAfter(s, ` `)
totalLen := 0
finalStr := ``
for _, each := range arr {
if (totalLen + len(each) > maxLen) {
fmt.Print(strings.TrimSpace(finalStr) + `...`)
break
}
totalLen += len(each)
finalStr += each
}
这是一个早已确立的事实...
//旧的错误答案
你必须使用字符串和切片:
var s = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English."
newS := s[:30 - 3]
newS += `...`
fmt.Print(newS)
结果 :It is a long established fa...