Как я могу эллиптически обрезать текст в golang? - PullRequest
1 голос
/ 28 января 2020

Я хотел бы иметь возможность аккуратно вырезать абзац, превышающий определенное количество символов, без вырезания слова в середине.

Так, например, это:

Это это давно установленный факт, что читатель будет отвлекаться на читаемое содержимое страницы при просмотре ее макета. Смысл использования Lorem Ipsum в том, что он имеет более-менее нормальное распределение букв, в отличие от использования «Контент здесь, контент здесь», что делает его похожим на читаемый Engli sh.

Должно стать:

Это давно установленный факт, что читатель будет отвлекаться на читаемый контент ...

Вот функция, которую я придумал с:

 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
}

Но это просто жестоко режет текст. Мне интересно, как я могу изменить (или заменить его на лучшее решение), чтобы вырезать текст эллиптически?

Ответы [ 3 ]

1 голос
/ 28 января 2020

Срезание строк может быть проблематичным c, потому что нарезка работает с байтами, а не с рунами. Диапазон, однако, работает с рунами:

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
0 голосов
/ 28 января 2020

Диапазон совершенно не нужен, как написано; как и сейчас, вся ваша функция может быть просто:

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]," .,:;-")]
}
0 голосов
/ 28 января 2020

Чтобы разделить в соответствии с пробелами и более, вы можете использовать регулярное выражение:

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

Вы можете делать такие вещи: Разделить вашу строку в срез и l oop через срез, пока общая длина вашей строки не превысит максимально допустимую длину.

    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...

...