Подтвердить что ты не робот

Усечь строку, не заканчивающуюся посередине слова

Я ищу способ усечения строки в Python, которая не будет обрезать строку в середине слова.

Например:

Original:          "This is really awesome."
"Dumb" truncate:   "This is real..."
"Smart" truncate:  "This is really..."

Я ищу способ выполнить "умную" усечку сверху.

4b9b3361

Ответ 1

Я на самом деле написал решение для этого в моем недавнем проекте. Я сжал большую часть его, чтобы быть немного меньше.

def smart_truncate(content, length=100, suffix='...'):
    if len(content) <= length:
        return content
    else:
        return ' '.join(content[:length+1].split(' ')[0:-1]) + suffix

Что происходит, так это if-statement, если ваш контент уже меньше точки отсечки. Если это не так, оно обрезается до нужной длины, разбивается на пространство, удаляет последний элемент (чтобы вы не отрезали слово), а затем соединяется с ним вместе (при использовании на "..." ).

Ответ 2

Здесь немного лучшая версия последней строки в решении Адама:

return content[:length].rsplit(' ', 1)[0]+suffix

(Это немного более эффективно и возвращает более разумный результат в случае отсутствия пробелов перед строкой.)

Ответ 3

Есть несколько тонкостей, которые могут или не могут быть для вас проблемой, например, обработка вкладок (например, если вы показываете их как 8 пробелов, но обрабатываете их как 1 символ внутри), обрабатывая различные варианты взлома и неразрывные пробелы, или разрешая разрывы при переносе и т.д. Если это желательно, вы можете взглянуть на модуль textwrap. например:

def truncate(text, max_size):
    if len(text) <= max_size:
        return text
    return textwrap.wrap(text, max_size-3)[0] + "..."

Поведение по умолчанию для слов, большее, чем max_size, заключается в их разбиении (что делает max_size жестким пределом). Вы можете перейти к мягкому пределу, используемому некоторыми другими решениями здесь, передав break_long_words = False to wrap(), и в этом случае оно вернет целое слово. Если вы хотите, чтобы это поведение изменило последнюю строку на:

    lines = textwrap.wrap(text, max_size-3, break_long_words=False)
    return lines[0] + ("..." if len(lines)>1 else "")

Есть несколько других параметров, таких как expand_tabs, которые могут представлять интерес, в зависимости от того, какое именно поведение вы хотите.

Ответ 4

def smart_truncate1(text, max_length=100, suffix='...'):
    """Returns a string of at most `max_length` characters, cutting
    only at word-boundaries. If the string was truncated, `suffix`
    will be appended.
    """

    if len(text) > max_length:
        pattern = r'^(.{0,%d}\S)\s.*' % (max_length-len(suffix)-1)
        return re.sub(pattern, r'\1' + suffix, text)
    else:
        return text

ИЛИ

def smart_truncate2(text, min_length=100, suffix='...'):
    """If the `text` is more than `min_length` characters long,
    it will be cut at the next word-boundary and `suffix`will
    be appended.
    """

    pattern = r'^(.{%d,}?\S)\s.*' % (min_length-1)
    return re.sub(pattern, r'\1' + suffix, text)

ИЛИ

def smart_truncate3(text, length=100, suffix='...'):
    """Truncates `text`, on a word boundary, as close to
    the target length it can come.
    """

    slen = len(suffix)
    pattern = r'^(.{0,%d}\S)\s+\S+' % (length-slen-1)
    if len(text) > length:
        match = re.match(pattern, text)
        if match:
            length0 = match.end(0)
            length1 = match.end(1)
            if abs(length0+slen-length) < abs(length1+slen-length):
                return match.group(0) + suffix
            else:
                return match.group(1) + suffix
    return text

Ответ 5

>>> import textwrap
>>> textwrap.wrap('The quick brown fox jumps over the lazy dog', 12)
['The quick', 'brown fox', 'jumps over', 'the lazy dog']

Вы просто берете первый элемент этого, и все готово...

Ответ 6

def smart_truncate(s, width):
    if s[width].isspace():
        return s[0:width];
    else:
        return s[0:width].rsplit(None, 1)[0]

Тестирование:

>>> smart_truncate('The quick brown fox jumped over the lazy dog.', 23) + "..."
'The quick brown fox...'

Ответ 7

Из Python 3.4+ вы можете использовать textwrap.shorten. Пример OP:

>>> import textwrap
>>> original = "This is really awesome."
>>> textwrap.shorten(original, width=20, placeholder="...")
'This is really...'

textwrap.shorten(текст, ширина, ** kwargs)

Свернуть и усечь заданный текст в соответствии с заданной шириной.

Сначала пробелы в тексте сбрасываются (все пробелы заменяются пробелами). Если результат соответствует ширине, это вернулся. В противном случае из слова опущено достаточно слов, чтобы оставшиеся слова плюс заполнитель в ширину: