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
@Anthony a slice
Marcelo Cantos

126

Ще коротше:

info = data[:75] + (data[75:] and '..')

2
Смішний підхід зробити це. Хоча це все-таки складений однолінійний. ^^
Веселий

3
чи не має це рішення 77 символів, якщо ви додасте ".."?
Марк Чакерян

це не виконання двох операцій з зрізом? Цікаво, як це працює в порівнянні з stackoverflow.com/a/52279347/1834057 , коли продуктивність вирішальна
Ніколас Гамільтон

1
Звичайно, приємна оригінальна відповідь, але відповідь Марсело краща, оскільки вона є більш чіткою і, таким чином, читабельною (і, таким чином, піфонічною).
sitnarf

114

Ще більш стисло:

data = data[:75]

Якщо вона менше 75 символів, змін не буде.


9
Імовірно, він хоче, щоб еліпсис був доданий, якщо рядок усічений.
FogleBird

4
Ти маєш рацію - я цього ніколи не помічав. Я не можу придумати кращого способу зробити це, ніж інші відповіді.
ніл

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
Начебто ламає штани на дійсно довгих струнах (без пробілів) і виводить лише еліпсис.
elBradford

5
@elBradford (та зацікавив інших): це тому, що shorten()обрізає слова , а не поодинокі символи. Я шукав, але не здається способом налаштувати shorten()або TextWrapperекземпляр відсікати окремі символи, а не слова.
Acsor

І це має дратівливий побічний ефект усунення розривів лінії
havlock

Це не вирішує питання ОП. Він обрізається словом і навіть видаляє пробіл.
Флоріан Вендельборн

32

Для рішення Джанго (про яке не згадувалося у запитанні):

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: HTML-скорочення Django


Це непотрібно поєднує логіку низького рівня з джанго. Не рекомендував би його.
Печера


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:]) * '..'


4
Я написав це лише для того, щоб показати, що це можливо. Це проти філософії читабельності пітона. Він не має жодних переваг у порівнянні з іншими методами на основі "якщо". Я ніколи не користуюся ним, і не пропоную вам використовувати його теж.
Сассан

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

Усі попередні відповіді нехтують, щоб врахувати, чого дійсно хотів ОП - вихідний рядок не більше 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'
       >>> 

1
Будь ласка, поясніть свою відповідь?
Gwenc37

подібний приклад цієї функції def info2 (data): if len (data)> 10: return data [: 10] + '...' else: повернення даних лямбда-інструкція безіменного дизайну у функціональному стилі ex = lambda x: x + 1 def ex (x): повернення x + 1
Spouk

1

Ви не можете насправді "обрізати" рядок Python, як ви можете зробити динамічно виділений рядок C. Струни в Python незмінні. Що ви можете зробити, це нарізати рядок, як описано в інших відповідях, що дає нову рядок, що містить лише символи, визначені зсувом і кроком фрагмента. У деяких (не практичних) випадках це може бути трохи прикро, наприклад, коли ви вибираєте Python як мову інтерв'ю, і інтерв'юер просить вас видалити дублікати символів зі строки на місці. До.


1
info = data[:min(len(data), 75)

Відповіді лише на код, як правило, вважаються низькою якістю. Чи можете ви додати пояснення до своєї відповіді.
Лимонний Казі

0

У регулярному виразі немає потреби, але ви хочете використовувати форматування рядків, а не конкатенацію рядків у прийнятому відповіді.

Це, мабуть, самий канонічний, пітонічний спосіб урізати рядок 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 ]

1
Що з усіма підкресленнями в кожному аргументі та змінній?
Ніколас Гамільтон

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.