Усечь строку, не заканчивающуюся посередине слова
Я ищу способ усечения строки в Python, которая не будет обрезать строку в середине слова.
Например:
Original: "This is really awesome."
"Dumb" truncate: "This is real..."
"Smart" truncate: "This is really..."
Я ищу способ выполнить "умную" усечку сверху.
Ответы
Ответ 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)
Свернуть и усечь заданный текст в соответствии с заданной шириной.
Сначала пробелы в тексте сбрасываются (все пробелы заменяются пробелами). Если результат соответствует ширине, это вернулся. В противном случае из слова опущено достаточно слов, чтобы оставшиеся слова плюс заполнитель в ширину: