Python trunca una cadena larga

245

¿Cómo se trunca una cadena a 75 caracteres en Python?

Así es como se hace en JavaScript:

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

Respuestas:

425
info = (data[:75] + '..') if len(data) > 75 else data
Marcelo Cantos
fuente
58
Cambiaría la condición quizás para len(data) > 77tener en cuenta los puntos dobles (no tiene sentido truncar solo el último carácter solo para reemplazarlo con un punto).
Hasen
55
@hasenj: Eso no se ajusta al código original, pero es una buena sugerencia que debería haber señalado en primer lugar.
Marcelo Cantos
2
Tenga en cuenta que los padres incluidos son, por supuesto, opcionales.
Taylor Edmiston
10
@TaylorEdmiston Cierto, pero son bastante útiles para aquellos que no recuerdan todas las reglas de precedencia en los 5 a 10 idiomas que usan a diario.
Marcelo Cantos
2
@Anthony a slice
Marcelo Cantos
126

Aún más corto:

info = data[:75] + (data[75:] and '..')
stanlekub
fuente
2
Enfoque divertido para hacerlo. Aunque todavía es una línea compuesta compuesta. ^^
Alegre
3
¿No tiene esta solución 77 caracteres si incluye el '..'?
Mark Chackerian
¿No es esto realizar dos operaciones de corte? Me pregunto cómo funciona esto en comparación con stackoverflow.com/a/52279347/1834057 , cuando el rendimiento es crucial
Nicholas Hamilton,
1
Claro, buena respuesta original, pero la respuesta de Marcelo es mejor ya que es más explícita y, por lo tanto, legible (y, por lo tanto, Pythonic).
sitnarf
114

Aún más conciso:

data = data[:75]

Si tiene menos de 75 caracteres, no habrá cambios.

neil
fuente
99
Presumiblemente, quiere que se anexen puntos suspensivos si la cadena se trunca.
FogleBird
44
Tienes razón, nunca me di cuenta de eso. No puedo pensar en una mejor manera de hacerlo que otras respuestas.
neil
82

Si está utilizando Python 3.4+, puede usarlo textwrap.shortendesde la biblioteca estándar:

Contraer y truncar el texto dado para que quepa en el ancho dado.

Primero, el espacio en blanco en el texto se contrae (todo el espacio en blanco se reemplaza por espacios individuales). Si el resultado se ajusta al ancho, se devuelve. De lo contrario, se sueltan suficientes palabras desde el final para que las palabras restantes más el marcador de posición encajen dentro del ancho:

>>> 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
fuente
8
Parece que se caga los pantalones con cuerdas realmente largas (sin espacios) y genera solo puntos suspensivos.
elBradford
55
@elBradford (y otros interesados): eso es porque shorten()trunca palabras , no caracteres individuales. Busqué pero no parece haber una forma de configurar shorten()o una TextWrapperinstancia para recortar caracteres individuales y no palabras.
Acsor
Y tiene el molesto efecto secundario de eliminar los saltos de línea
havlock el
Esto no resuelve la pregunta de OP. Se trunca por palabra e incluso elimina espacios en blanco.
Florian Wendelborn
9

Podrías usar este one-liner:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
fuente
2
¿Cómo se [:n]llama para que pueda buscarlo en la documentación?
oldboy
9

Con regex:

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

Las cadenas largas se truncan:

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

Las cadenas más cortas nunca se truncan:

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

De esta manera, también puede "cortar" la parte media de la cadena, que en algunos casos es más agradable:

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
fuente
bueno, eso no funcionó cuando tienes espacios en tu cadena
holms
¿Por qué usarías regex para un caso tan simple?
Bora M. Alper
5

Este método no usa ninguno si:

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

Sassan
fuente
44
Lo escribí solo para mostrar que es posible. Va en contra de la filosofía de legibilidad de Python. No tiene ninguna ventaja de rendimiento en comparación con otros métodos basados ​​en "si". Nunca lo uso y no te sugiero que lo uses también.
Sassan el
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Hola Adios
fuente
1
Esta es la solución más elegante. Además, extraería el límite de caracteres (en este caso 75) en una variable para evitar inconsistencias. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Otra solución más. Con Truey Falseobtienes un pequeño comentario sobre la prueba al final.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
El verdadero Bugeater
fuente
2

Esto acaba de entrar:

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
fuente
Todas las respuestas anteriores no consideran lo que realmente quería el OP: una cadena de salida de no más de 75 caracteres. Felicitaciones por entender el principio de programación "no hagas lo que digo, haz lo que quiero". Para completar, puede arreglar el caso de la esquina de n <3 agregando: si n> 2 más s [: n]
Dave
1
       >>> info = lambda data: len(data)>10 and data[:10]+'...' or data
       >>> info('sdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf')
           'sdfsdfsdfs...'
       >>> info('sdfsdf')
           'sdfsdf'
       >>> 
Spouk
fuente
1
¿Por favor explica tu respuesta?
Gwenc37
ejemplo similar de esta función def info2 (data): if len (data)> 10: return data [: 10] + '...' else: return data instrucción lambda del diseño sin nombre en un estilo funcional ex = lambda x: x + 1 def ex (x): retorno x + 1
Spouk
1

En realidad, no puede "truncar" una cadena de Python como puede hacer una cadena C asignada dinámicamente. Las cadenas en Python son inmutables. Lo que puede hacer es cortar una cadena como se describe en otras respuestas, produciendo una nueva cadena que contiene solo los caracteres definidos por las compensaciones de corte y el paso. En algunos casos (no prácticos) esto puede ser un poco molesto, como cuando elige Python como idioma de la entrevista y el entrevistador le pide que elimine los caracteres duplicados de una cadena en el lugar. Doh

Dave
fuente
1
info = data[:min(len(data), 75)
Jesse
fuente
Las respuestas de solo código generalmente se consideran de baja calidad. ¿Podría agregar una explicación a su respuesta?
Lemon Kazi
0

No hay necesidad de una expresión regular, pero sí desea utilizar el formato de cadena en lugar de la concatenación de cadena en la respuesta aceptada.

Esta es probablemente la forma más canónica y pitónica de truncar la cadena dataa 75 caracteres.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Adam Nelson
fuente
Me pareció curioso cómo se saddddddd...convierte tu cadena 111111...:) Sé que es un error tipográfico copiar y pegar, y estoy de acuerdo contigo sobre las expresiones regulares.
akarilimano
0

Aquí hay una función que hice como parte de una nueva clase de Cadena ... Permite agregar un sufijo (si la cadena es de tamaño después de recortar y agregar es lo suficientemente larga, aunque no es necesario forzar el tamaño absoluto)

Estaba en el proceso de cambiar algunas cosas, por lo que hay algunos costos lógicos inútiles (si _truncate ... por ejemplo) donde ya no es necesario y hay un retorno en la parte superior ...

Pero, sigue siendo una buena función para truncar datos ...

##
## 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
fuente
1
¿Qué pasa con todos los guiones bajos en cada argumento y variable?
Nicholas Hamilton el
0
info = data[:75] + ('..' if len(data) > 75 else '')
Hola Adios
fuente