Python обрезать длинную строку

246

Как укоротить строку до 75 символов в Python?

Вот как это делается в JavaScript:

var data="saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
var info = (data.length > 75) ? data.substring[0,75] + '..' : data;
килектор
источник

Ответы:

427
info = (data[:75] + '..') if len(data) > 75 else data
Марсело Кантос
источник
58
Я бы изменил условие, возможно, чтобы len(data) > 77учесть двойные точки (нет смысла урезать только последний символ только для замены его точкой).
hasen
5
@hasenj: Это не соответствует исходному коду, но это хорошее предложение, на которое я должен был указать в первую очередь.
Марсело Кантос
2
Обратите внимание, что включенные в комплект скобки, конечно, не обязательны.
Тейлор Эдмистон
10
@TaylorEdmiston Верно, но они весьма полезны для тех, кто не помнит все правила приоритета для 5–10 языков, которые они используют ежедневно.
Марсело Кантос
2
@ Энтони кусочек
Марсело Кантос,
126

Еще короче

info = data[:75] + (data[75:] and '..')
stanlekub
источник
2
Забавный подход к этому. Хотя это все еще составной однострочный. ^^
Веселый
3
Разве это решение не имеет 77 символов, если вы включаете «..»?
Марк Чакериан
это не выполнение двух операций среза? Интересно, как это работает по сравнению со, скажем, stackoverflow.com/a/52279347/1834057 , когда производительность имеет решающее значение
Николас Гамильтон
1
Конечно, хороший оригинальный ответ, но ответ Марсело лучше, так как он более явный и, следовательно, читаемый (и, следовательно, Pythonic).
Ситнарф
114

Еще более лаконично:

data = data[:75]

Если оно меньше 75 символов, изменений не будет.

Neil
источник
9
Предположительно он хочет добавить многоточие, если строка обрезана.
FogleBird
4
Ты прав - я этого никогда не замечал. Я не могу придумать лучшего способа сделать это, чем другие ответы.
Neil
82

Если вы используете Python 3.4+, вы можете использовать textwrap.shortenиз стандартной библиотеки:

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

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

>>> textwrap.shorten("Hello  world!", width=12)
'Hello world!'
>>> textwrap.shorten("Hello  world!", width=11)
'Hello [...]'
>>> textwrap.shorten("Hello world", width=10, placeholder="...")
'Hello...'
Бора М. Альпер
источник
8
Кажется, он обвивает штаны очень длинными струнами (без пробелов) и выдает только многоточие.
ЭльБрадфорд,
5
@elBradford (и другие заинтересованные): это потому, что shorten()усекает слова , а не отдельные символы. Я искал, но, похоже, нет способа настроить shorten()или создать TextWrapperэкземпляр для обрезки отдельных символов, а не слов.
Acsor
И у этого есть раздражающий побочный эффект удаления разрывов строки
havlock
Это не решает вопрос ОП. Он усекает слово и даже удаляет пробелы.
Флориан Вендельборн
32

Для решения Django (которое не было упомянуто в вопросе):

from django.utils.text import Truncator
value = Truncator(value).chars(75)

Взгляните на исходный код Truncator, чтобы оценить проблему: https://github.com/django/django/blob/master/django/utils/text.py#L66

По поводу усечения с Django: усечение Django HTML

Risadinha
источник
Это без необходимости соединяет низкоуровневую логику с django. Не рекомендовал бы это.
Пещерный человек
9

Вы можете использовать этот однострочник:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
источник
2
что [:n]называется, чтобы я мог посмотреть это в документации?
старик
2
Нарезка: stackoverflow.com/questions/509211/…
Bl00dh0und
9

С регулярным выражением:

re.sub(r'^(.{75}).*$', '\g<1>...', data)

Длинные строки усекаются:

>>> data="11111111112222222222333333333344444444445555555555666666666677777777778888888888"
>>> re.sub(r'^(.{75}).*$', '\g<1>...', data)
'111111111122222222223333333333444444444455555555556666666666777777777788888...'

Более короткие строки никогда не усекаются:

>>> data="11111111112222222222333333"
>>> re.sub(r'^(.{75}).*$', '\g<1>...', data)
'11111111112222222222333333'

Таким образом, вы также можете «вырезать» среднюю часть строки, что в некоторых случаях лучше:

re.sub(r'^(.{5}).*(.{5})$', '\g<1>...\g<2>', data)

>>> data="11111111112222222222333333333344444444445555555555666666666677777777778888888888"
>>> re.sub(r'^(.{5}).*(.{5})$', '\g<1>...\g<2>', data)
'11111...88888'
Давид Герри
источник
хорошо, что не сработало, когда у вас есть пробелы в строке
Holms
Почему вы используете регулярное выражение для такого простого случая?
Бора М. Альпер
5

Этот метод не использует, если:

data[:75] + bool(data[75:]) * '..'

Sassan
источник
4
Я написал это только для того, чтобы показать, что это возможно. Это противоречит философии читабельности Python. Он не имеет никакого преимущества в производительности по сравнению с другими методами «если». Я никогда не использую это, и я не предлагаю вам использовать это тоже.
Сассан
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Привет пока
источник
1
Это самое элегантное решение. Кроме того, я бы выделил предел символов (в данном случае 75) в переменную, чтобы избежать несоответствий. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Еще одно решение. С, Trueи Falseвы получите небольшой отзыв о тесте в конце.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
Истинный Бюджетер
источник
2

Это только в:

n = 8
s = '123'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '12345678'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '123456789'     
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]
s = '123456789012345'
print  s[:n-3] + (s[n-3:], '...')[len(s) > n]

123
12345678
12345...
12345...
dansalmo
источник
Во всех предыдущих ответах не учитывается то, чего действительно хотел ОП - строка вывода длиной не более 75 символов. Слава за понимание принципа «не делай, что я говорю, делай, что я хочу». Для полноты вы можете исправить угловой случай n <3, добавив: если n> 2 else s [: n]
Дейв
1
       >>> info = lambda data: len(data)>10 and data[:10]+'...' or data
       >>> info('sdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf')
           'sdfsdfsdfs...'
       >>> info('sdfsdf')
           'sdfsdf'
       >>> 
Spouk
источник
1
Пожалуйста, объясните свой ответ?
Gwenc37
аналогичный пример этой функции def info2 (data): if len (data)> 10: вернуть данные [: 10] + '...' else: вернуть команду lambda безымянного дизайна в функциональном стиле ex = lambda x: x + 1 def ex (x): возврат x + 1
Spouk
1

На самом деле вы не можете "усечь" строку Python, как вы можете создать динамически размещаемую строку C. Строки в Python неизменны. Что вы можете сделать, это нарезать строку, как описано в других ответах, получив новую строку, содержащую только символы, определенные смещениями и шагом среза. В некоторых (непрактичных) случаях это может немного раздражать, например, когда вы выбираете Python в качестве языка интервью, и интервьюер просит вас удалить повторяющиеся символы из строки на месте. Doh.

Дейв
источник
1
info = data[:min(len(data), 75)
Джесси
источник
Ответы только кода обычно считаются некачественными. Не могли бы вы добавить объяснение к вашему ответу.
Лимон Кази
0

Регулярное выражение не нужно, но вы хотите использовать форматирование строк, а не конкатенацию строк в принятом ответе.

Это, вероятно, самый канонический, Pythonic способ обрезать строку dataдо 75 символов.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Адам Нельсон
источник
Мне показалось забавным, как ваша saddddddd...строка превращается 111111...:) Я знаю, что это опечатка, хотя я согласен с вами по поводу регулярных выражений.
Акарилимано
0

Вот функция, которую я сделал как часть нового класса String ... Она позволяет добавлять суффикс (если строка имеет размер после обрезки, а добавление достаточно длинное - хотя вам не нужно устанавливать абсолютный размер)

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

Но это все еще хорошая функция для усечения данных ...

##
## Truncate characters of a string after _len'nth char, if necessary... If _len is less than 0, don't truncate anything... Note: If you attach a suffix, and you enable absolute max length then the suffix length is subtracted from max length... Note: If the suffix length is longer than the output then no suffix is used...
##
## Usage: Where _text = 'Testing', _width = 4
##      _data = String.Truncate( _text, _width )                        == Test
##      _data = String.Truncate( _text, _width, '..', True )            == Te..
##
## Equivalent Alternates: Where _text = 'Testing', _width = 4
##      _data = String.SubStr( _text, 0, _width )                       == Test
##      _data = _text[  : _width ]                                      == Test
##      _data = ( _text )[  : _width ]                                  == Test
##
def Truncate( _text, _max_len = -1, _suffix = False, _absolute_max_len = True ):
    ## Length of the string we are considering for truncation
    _len            = len( _text )

    ## Whether or not we have to truncate
    _truncate       = ( False, True )[ _len > _max_len ]

    ## Note: If we don't need to truncate, there's no point in proceeding...
    if ( not _truncate ):
        return _text

    ## The suffix in string form
    _suffix_str     = ( '',  str( _suffix ) )[ _truncate and _suffix != False ]

    ## The suffix length
    _len_suffix     = len( _suffix_str )

    ## Whether or not we add the suffix
    _add_suffix     = ( False, True )[ _truncate and _suffix != False and _max_len > _len_suffix ]

    ## Suffix Offset
    _suffix_offset = _max_len - _len_suffix
    _suffix_offset  = ( _max_len, _suffix_offset )[ _add_suffix and _absolute_max_len != False and _suffix_offset > 0 ]

    ## The truncate point.... If not necessary, then length of string.. If necessary then the max length with or without subtracting the suffix length... Note: It may be easier ( less logic cost ) to simply add the suffix to the calculated point, then truncate - if point is negative then the suffix will be destroyed anyway.
    ## If we don't need to truncate, then the length is the length of the string.. If we do need to truncate, then the length depends on whether we add the suffix and offset the length of the suffix or not...
    _len_truncate   = ( _len, _max_len )[ _truncate ]
    _len_truncate   = ( _len_truncate, _max_len )[ _len_truncate <= _max_len ]

    ## If we add the suffix, add it... Suffix won't be added if the suffix is the same length as the text being output...
    if ( _add_suffix ):
        _text = _text[ 0 : _suffix_offset ] + _suffix_str + _text[ _suffix_offset: ]

    ## Return the text after truncating...
    return _text[ : _len_truncate ]
Acecool
источник
1
Что со всеми подчеркиваниями в каждом аргументе и переменной?
Николас Гамильтон
0
info = data[:75] + ('..' if len(data) > 75 else '')
Привет пока
источник