Python obcina długi ciąg

246

Jak obciąć ciąg znaków do 75 znaków w Pythonie?

Oto jak to się robi w JavaScript:

var data="saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
var info = (data.length > 75) ? data.substring[0,75] + '..' : data;
Ponton
źródło

Odpowiedzi:

427
info = (data[:75] + '..') if len(data) > 75 else data
Marcelo Cantos
źródło
58
Może zmieniłbym warunek, len(data) > 77aby uwzględnić podwójne kropki (nie ma sensu obcinać tylko ostatniego znaku, aby zastąpić go kropką).
hasen
5
@hasenj: To nie byłoby zgodne z oryginalnym kodem, ale to dobra sugestia, którą powinienem był przede wszystkim wskazać.
Marcelo Cantos
2
Pamiętaj, że dołączone pareny są oczywiście opcjonalne.
Taylor Edmiston
10
@TaylorEdmiston To prawda, ale są one bardzo pomocne dla tych, którzy nie pamiętają wszystkich zasad pierwszeństwa w 5–10 językach, z których codziennie korzystają.
Marcelo Cantos
2
@Anthony a slice
Marcelo Cantos
126

Jeszcze krótszy:

info = data[:75] + (data[75:] and '..')
stanlekub
źródło
2
Zabawne podejście do tego. Choć nadal jest to kompozytowy jednowarstwowy. ^^
Radosny
3
czy to rozwiązanie nie ma 77 znaków, jeśli dodasz „..”?
Mark Chackerian
czy to nie wykonuje dwóch operacji wycinania? Zastanawiam się, jak to działa w porównaniu do powiedzmy stackoverflow.com/a/52279347/1834057 , kiedy wydajność jest kluczowa
Nicholas Hamilton,
1
Jasne, miła, oryginalna odpowiedź, ale odpowiedź Marcelo jest lepsza, ponieważ jest bardziej wyraźna, a tym samym czytelna (a więc pytoniczna).
sitnarf,
114

Jeszcze bardziej zwięzłe:

data = data[:75]

Jeśli ma mniej niż 75 znaków, nie będzie żadnych zmian.

neil
źródło
9
Przypuszczalnie chce dołączyć elipsę, jeśli łańcuch zostanie obcięty.
FogleBird
4
Masz rację - nigdy tego nie zauważyłem. Nie mogę wymyślić lepszego sposobu na zrobienie tego niż inne odpowiedzi.
neil
82

Jeśli używasz Python 3.4+, możesz użyć textwrap.shortenze standardowej biblioteki:

Zwiń i skróć podany tekst, aby pasował do podanej szerokości.

Najpierw białe znaki w tekście są zwinięte (wszystkie białe znaki są zastępowane pojedynczymi spacjami). Jeśli wynik mieści się w szerokości, jest zwracany. W przeciwnym razie wystarczająca liczba słów zostanie usunięta z końca, aby pozostałe słowa plus symbol zastępczy pasowały do ​​szerokości:

>>> textwrap.shorten("Hello  world!", width=12)
'Hello world!'
>>> textwrap.shorten("Hello  world!", width=11)
'Hello [...]'
>>> textwrap.shorten("Hello world", width=10, placeholder="...")
'Hello...'
Bora M. Alper
źródło
8
Wygląda na to, że gówno ma spodnie na naprawdę długich sznurkach (bez spacji) i generuje tylko elipsę.
elBradford
5
@elBradford (i zainteresowani inni): to dlatego, że shorten()obcina słowa , a nie pojedyncze znaki. Szukałem, ale nie ma sposobu na konfigurację shorten()ani TextWrapperinstancji do przycinania pojedynczych znaków, a nie słów.
Acsor,
I ma irytujący efekt uboczny usuwania przerw linii
havlock
To nie rozwiązuje pytania OP. Obcina słowo, a nawet usuwa białe znaki.
Florian Wendelborn
9

Możesz użyć tego jednowierszowego:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
źródło
2
jak się [:n]nazywa, żebym mógł to sprawdzić w dokumentacji?
oldboy
9

Z wyrażeniem regularnym:

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

Długie łańcuchy są obcinane:

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

Krótsze łańcuchy nigdy nie są obcinane:

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

W ten sposób możesz także „wyciąć” środkową część sznurka, co w niektórych przypadkach jest ładniejsze:

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

>>> data="11111111112222222222333333333344444444445555555555666666666677777777778888888888"
>>> re.sub(r'^(.{5}).*(.{5})$', '\g<1>...\g<2>', data)
'11111...88888'
Davide Guerri
źródło
dobrze, że to nie zadziałało, gdy masz spacje w łańcuchu
holms
Dlaczego miałbyś używać wyrażenia regularnego w tak prostym przypadku?
Bora M. Alper,
5

Ta metoda nie używa żadnej, jeśli:

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

Sassan
źródło
4
Napisałem to tylko po to, aby pokazać, że to możliwe. Jest to sprzeczne z filozofią czytelności Pythona. Nie ma żadnej przewagi wydajności w porównaniu z innymi metodami opartymi na „jeśli”. Nigdy go nie używam i nie sugeruję, żebyś go również używał.
Sassan
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Cześć Żegnaj
źródło
1
To najbardziej eleganckie rozwiązanie. Dodatkowo wyodrębnię limit znaków (w tym przypadku 75) do zmiennej, aby uniknąć niespójności. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Jeszcze inne rozwiązanie. Dzięki, Truea Falsena końcu otrzymasz małą informację zwrotną na temat testu.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
Prawdziwy Bugeater
źródło
2

To tylko w:

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
źródło
Wszystkie poprzednie odpowiedzi pomijają rozważanie tego, czego OP naprawdę chciał - ciąg wyjściowy nie dłuższy niż 75 znaków. Wyrazy uznania za zrozumienie zasady programowania „nie rób tego, co mówię, rób co chcę”. Dla kompletności możesz naprawić przypadek narożnika n <3, dodając: jeśli n> 2 else s [: n]
Dave
1
       >>> info = lambda data: len(data)>10 and data[:10]+'...' or data
       >>> info('sdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf')
           'sdfsdfsdfs...'
       >>> info('sdfsdf')
           'sdfsdf'
       >>> 
Spouk
źródło
1
Proszę wyjaśnić swoją odpowiedź?
Gwenc37
podobny przykład tej funkcji def info2 (data): if len (data)> 10: return data [: 10] + '...' else: return data instrukcja lambda bezimiennego projektu w stylu funkcjonalnym ex = lambda x: x + 1 def ex (x): return x + 1
Spouk
1

Nie można tak naprawdę „obciąć” łańcucha Pythona, tak jak można zrobić dynamicznie przydzielany ciąg C. Ciągi w Pythonie są niezmienne. To, co możesz zrobić, to pokroić ciąg, jak opisano w innych odpowiedziach, uzyskując nowy ciąg zawierający tylko znaki zdefiniowane przez przesunięcia plasterka i krok. W niektórych (niepraktycznych) przypadkach może to być trochę denerwujące, na przykład gdy wybierasz Python jako język wywiadu, a ankieter prosi cię o usunięcie zduplikowanych znaków z łańcucha w miejscu. Doh

Dave
źródło
1
info = data[:min(len(data), 75)
Jesse
źródło
Tylko odpowiedzi na kod są ogólnie uważane za niskiej jakości. Czy możesz dodać wyjaśnienie do swojej odpowiedzi?
Lemon Kazi,
0

Wyrażenie regularne nie jest potrzebne, ale chcesz użyć formatowania łańcucha zamiast konkatenacji łańcucha w zaakceptowanej odpowiedzi.

Jest to prawdopodobnie najbardziej kanoniczny, Pythoński sposób obcinania łańcucha datao długości 75 znaków.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Adam Nelson
źródło
To zabawne, jak saddddddd...zmienia się Twój ciąg 111111...:) Wiem, że to literówka kopiuj-wklej i zgadzam się z tobą w wyrażeniach regularnych.
akarilimano
0

Oto funkcja, którą utworzyłem w ramach nowej klasy String ... Pozwala na dodanie sufiksu (jeśli łańcuch ma rozmiar po przycięciu i jest wystarczająco długi - chociaż nie musisz wymuszać rozmiaru bezwzględnego)

Byłem w trakcie zmiany kilku rzeczy, więc są pewne bezużyteczne koszty logiczne (jeśli na przykład skracam ...), gdzie nie jest to już konieczne, a na górze jest zwrot ...

Ale nadal jest to dobra funkcja do obcinania danych ...

##
## 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
źródło
1
co ze wszystkimi podkreśleniami w każdym pojedynczym argumencie i zmiennej?
Nicholas Hamilton
0
info = data[:75] + ('..' if len(data) > 75 else '')
Cześć Żegnaj
źródło