【问题标题】:How can I elliptically truncate text in golang?如何在golang中椭圆截断文本?
【发布时间】:2020-05-14 05:49:01
【问题描述】:

我希望能够干净地剪切大于一定字符数的段落,而不会在中间剪切一个单词。

例如:

读者会被 查看其布局时页面的可读内容。的点 使用 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
}

但它只是粗暴地削减了文本。我想知道如何修改(或用更好的解决方案替换它)以椭圆地剪切文本?

【问题讨论】:

    标签: string go truncate


    【解决方案1】:

    切片字符串可能会出现问题,因为切片适用于字节,而不是符文。然而,范围适用于符文:

    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
    

    【讨论】:

    • 像魅力一样工作。谢谢!
    【解决方案2】:

    这个范围是完全没有必要写的;就像现在一样,您的整个功能可能只是:

    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]," .,:;-")]
    }
    

    【讨论】:

    • 这可能不是多字节安全的。
    • @BurakSerdar 你是什么意思?
    • 字符串切片操作将字符串视为字节切片。如果字符串包含多字节字符,则 s[:max] 将不是剪切它的正确位置。
    • @Adrian,感谢您的提示,但这有一些缺点:1. 当字符串中有换行符时会出错。 2. 当文本长度短于max时出现恐慌。
    • @BurakSerdar 你的解决方案是什么?
    【解决方案3】:

    要根据空格等进行拆分,可以使用正则表达式:

    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 long\nestablished fact that a reader\nwill\nbe 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...

    【讨论】:

    • 问题的第一行:“我希望能够干净地剪切大于一定字符数的段落,而不会在中间剪切一个单词。”
    • 我的错,我用一个可行的解决方案更新了我的答案
    • 容易理解,但不处理文本中有换行符的情况。所以不够健壮。
    • 如果你想在空格、换行符、制表符等上分割,你需要在想要的值之后分割原始字符串。我更新了我原来的答案。
    猜你喜欢
    • 2022-12-10
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多