Python truncar uma cadeia longa

245

Como alguém trunca uma string com 75 caracteres em Python?

É assim que é feito em JavaScript:

var data="saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
var info = (data.length > 75) ? data.substring[0,75] + '..' : data;
Hulk
fonte

Respostas:

424
info = (data[:75] + '..') if len(data) > 75 else data
Marcelo Cantos
fonte
58
Talvez eu mudasse a condição para len(data) > 77dar conta dos pontos duplos (é inútil truncar apenas o último caractere apenas para substituí-lo por um ponto).
hasen
5
@hasenj: Isso não está em conformidade com o código original, mas é uma boa sugestão que eu deveria ter apontado em primeiro lugar.
Marcelo Cantos
2
Observe que as parênteses incluídas são obviamente opcionais.
Taylor Edmiston
10
@TaylorEdmiston True, mas são bastante úteis para aqueles que não se lembram de todas as regras de precedência nos 5–10 idiomas que usam diariamente.
Marcelo Cantos
2
@Anthony a slice
Marcelo Cantos
126

Ainda mais curto:

info = data[:75] + (data[75:] and '..')
stanlekub
fonte
2
Abordagem engraçada para fazê-lo. Embora ainda seja uma linha composta. ^^
Animado
3
essa solução não possui 77 caracteres se você incluir o '..'?
Mark Chackerian
isso não está executando duas operações de fatia? Pergunto-me como este executa em comparação a dizer stackoverflow.com/a/52279347/1834057 , quando o desempenho é crucial
Nicholas Hamilton
1
Claro, boa resposta original, mas a resposta de Marcelo é melhor, pois é mais explícita e, portanto, legível (e, portanto, pitônica).
sitnarf 19/09/19
114

Ainda mais conciso:

data = data[:75]

Se tiver menos de 75 caracteres, não haverá alterações.

neil
fonte
9
Presumivelmente, ele quer uma elipse anexada se a sequência estiver truncada.
FogleBird 20/05
4
Você está certo - eu nunca percebi isso. Não consigo pensar em uma maneira melhor de fazer isso do que em outras respostas.
neil
82

Se você estiver usando o Python 3.4+, poderá usar a textwrap.shortenpartir da biblioteca padrão:

Recolha e trunque o texto fornecido para caber na largura especificada.

Primeiro, o espaço em branco no texto é recolhido (todo o espaço em branco é substituído por espaços únicos). Se o resultado couber na largura, ele é retornado. Caso contrário, palavras suficientes serão descartadas do final para que as palavras restantes e o espaço reservado se ajustem à largura:

>>> 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
fonte
8
Parece cagar suas calças em cordas muito longas (sem espaços) e produz apenas as reticências.
27417 elBradford
5
@elBradford (e outros interessados): isso ocorre porque shorten()trunca palavras , não caracteres únicos. Eu procurei, mas não parece haver uma maneira de configurar shorten()ou uma TextWrapperinstância para recortar caracteres únicos e não palavras.
Acsor
E tem o efeito colateral desagradável de remover quebras de linha
havlock
Isso não resolve a questão do OP. Ele trunca por palavra e até remove espaços em branco.
Florian Wendelborn
9

Você pode usar esta linha:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
fonte
2
o que é [:n]chamado para que eu possa procurar na documentação?
oldboy 29/09
2
Slicing: stackoverflow.com/questions/509211/…
Bl00dh0und 1/01/18
9

Com regex:

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

Seqüências longas são truncadas:

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

Strings mais curtas nunca são truncadas:

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

Dessa forma, você também pode "cortar" a parte do meio da string, o que é melhor em alguns casos:

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
fonte
bem que não funcionou quando você tem espaços em sua corda
holms
Por que você usaria regex para um caso tão simples?
Bora M. Alper
5

Este método não usa nenhum se:

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

Sassan
fonte
4
Escrevi apenas para mostrar que é possível. É contra a filosofia de legibilidade do python. Não possui nenhuma vantagem de desempenho em comparação com outros métodos baseados em "se". Eu nunca uso e não sugiro que você use também.
Sassan
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Olá adeus
fonte
1
Esta é a solução mais elegante. Além disso, eu extrairia o limite de caracteres (neste caso 75) em uma variável para evitar inconsistências. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Mais uma solução. Com Truee Falsevocê recebe um pequeno feedback sobre o teste no final.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
O verdadeiro Bugeater
fonte
2

Isso apenas em:

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
fonte
Todas as respostas anteriores não consideram o que o OP realmente queria - uma sequência de saída com no máximo 75 caracteres. Parabéns por entender o princípio de programação "não faça o que eu digo, faça o que eu quero". Para completar, você pode corrigir a caixa de canto de n <3 anexando: if 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
fonte
1
Por favor, explique sua resposta?
Gwenc37
exemplo semelhante dessa função def info2 (data): se len (data)> 10: retornar dados [: 10] + '...' else: retornar dados instrução lambda do design sem nome em um estilo funcional ex = lambda x: x + 1 def ex (x): retorna x + 1
Spouk
1

Na verdade, você não pode "truncar" uma cadeia de caracteres Python como uma cadeia C alocada dinamicamente. Strings em Python são imutáveis. O que você pode fazer é cortar uma sequência como descrito em outras respostas, produzindo uma nova sequência contendo apenas os caracteres definidos pelas compensações e pela etapa da fatia. Em alguns casos (não práticos), isso pode ser um pouco chato, como quando você escolhe Python como sua linguagem de entrevista e o entrevistador pede para você remover caracteres duplicados de uma string no local. Doh.

Dave
fonte
1
info = data[:min(len(data), 75)
Jesse
fonte
As respostas somente de código são geralmente consideradas de baixa qualidade. Você poderia adicionar uma explicação para sua resposta.
Lemon Kazi
0

Não há necessidade de uma expressão regular, mas você deseja usar a formatação de sequência em vez da concatenação de sequência na resposta aceita.

Esta é provavelmente a maneira Python mais canônica de truncar a string datacom 75 caracteres.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Adam Nelson
fonte
Achei engraçado como sua saddddddd...string se transforma 111111...:) No entanto, eu sei que é um erro de copiar e colar e concordo com você sobre expressões regulares.
akarilimano
0

Aqui está uma função que eu fiz como parte de uma nova classe String ... Permite adicionar um sufixo (se a string for do tamanho após o corte e a adição for longa o suficiente - embora você não precise forçar o tamanho absoluto)

Eu estava no processo de mudar algumas coisas para que houvesse alguns custos lógicos inúteis (se _ truncados ... por exemplo), onde não é mais necessário e há um retorno no topo ...

Mas, ainda é uma boa função para truncar dados ...

##
## 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
fonte
1
O que há com todos os sublinhados em cada argumento e variável?
Nicholas Hamilton
0
info = data[:75] + ('..' if len(data) > 75 else '')
Olá adeus
fonte