Python tronque une longue chaîne

245

Comment tronquer une chaîne à 75 caractères en Python?

Voici comment cela se fait en JavaScript:

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

Réponses:

425
info = (data[:75] + '..') if len(data) > 75 else data
Marcelo Cantos
la source
58
Je changerais peut-être la condition pour len(data) > 77tenir compte des doubles points (il est inutile de tronquer uniquement le dernier caractère uniquement pour le remplacer par un point).
hasen
5
@hasenj: Cela ne serait pas conforme au code d'origine, mais c'est une bonne suggestion que j'aurais dû signaler en premier lieu.
Marcelo Cantos
2
Notez que les parens inclus sont bien sûr facultatifs.
Taylor Edmiston
10
@TaylorEdmiston Vrai, mais ils sont très utiles pour ceux qui ne se souviennent pas de toutes les règles de priorité dans les 5 à 10 langues qu'ils utilisent quotidiennement.
Marcelo Cantos
2
@Anthony a slice
Marcelo Cantos
126

Encore plus court:

info = data[:75] + (data[75:] and '..')
stanlekub
la source
2
Approche drôle pour le faire. Bien qu'il s'agisse toujours d'une doublure composite. ^^
Joyeux
3
cette solution ne contient-elle pas 77 caractères si vous incluez le '..'?
Mark Chackerian
n'est-ce pas effectuer deux opérations de tranche? Je me demande comment cela fonctionne par rapport à disons stackoverflow.com/a/52279347/1834057 , lorsque les performances sont cruciales
Nicholas Hamilton
1
Bien sûr, belle réponse originale, mais la réponse de Marcelo est meilleure car elle est plus explicite et donc lisible (et donc Pythonique).
sitnarf
114

Encore plus concis:

data = data[:75]

S'il est inférieur à 75 caractères, il n'y aura aucun changement.

neil
la source
9
Vraisemblablement, il veut ajouter des points de suspension si la chaîne est tronquée.
FogleBird
4
Tu as raison - je ne l'ai jamais remarqué. Je ne peux pas penser à une meilleure façon de faire que les autres réponses.
neil
82

Si vous utilisez Python 3.4+, vous pouvez utiliser à textwrap.shortenpartir de la bibliothèque standard:

Réduisez et tronquez le texte donné pour qu'il tienne dans la largeur donnée.

Tout d'abord, les espaces dans le texte sont réduits (tous les espaces sont remplacés par des espaces simples). Si le résultat tient dans la largeur, il est renvoyé. Sinon, suffisamment de mots sont supprimés de la fin pour que les mots restants plus l'espace réservé tiennent dans la largeur:

>>> 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
la source
8
Il semble accrocher son pantalon sur de très longues cordes (sans espaces) et ne sort que les points de suspension.
elBradford
5
@elBradford (et les autres intéressés): c'est parce que shorten()tronque les mots , pas les caractères simples. J'ai cherché mais il ne semble pas y avoir de moyen de configurer shorten()ou d' TextWrapperinstance pour couper des caractères uniques et non des mots.
Acsor
Et cela a pour effet secondaire ennuyeux de supprimer les sauts de ligne
havlock
Cela ne résout pas la question d'OP. Il tronque par mot et supprime même les espaces.
Florian Wendelborn le
9

Vous pouvez utiliser ce one-liner:

data = (data[:75] + '..') if len(data) > 75 else data
phoenix24
la source
2
comment [:n]s'appelle-t-on pour que je puisse le chercher dans la documentation?
oldboy
2
Tranchage: stackoverflow.com/questions/509211/…
Bl00dh0und
9

Avec regex:

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

Les chaînes longues sont tronquées:

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

Les chaînes plus courtes ne sont jamais tronquées:

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

De cette façon, vous pouvez également "couper" la partie médiane de la chaîne, ce qui est plus agréable dans certains cas:

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
la source
Eh
Pourquoi utiliseriez-vous regex pour un cas aussi simple?
Bora M. Alper
5

Cette méthode n'en utilise pas si:

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

Sassan
la source
4
Je l'ai écrit uniquement pour montrer que c'est possible. C'est contraire à la philosophie de lisibilité de python. Il n'a aucun avantage en termes de performances par rapport aux autres méthodes basées sur le "si". Je ne l'utilise jamais et je ne vous suggère pas de l'utiliser aussi.
Sassan
4
limit = 75
info = data[:limit] + '..' * (len(data) > limit)
Bonjour au revoir
la source
1
C'est la solution la plus élégante. De plus, j'extrais la limite de caractères (dans ce cas 75) dans une variable pour éviter les incohérences. limit = 75; info = data[:limit] + '..' * (len(data) > limit)
ekauffmann
3

Encore une autre solution. Avec Trueet Falsevous obtenez un petit retour sur le test à la fin.

data = {True: data[:75] + '..', False: data}[len(data) > 75]
Le Véritable Bugeater
la source
2

Ceci juste en:

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
la source
Toutes les réponses précédentes négligent de considérer ce que l'OP voulait vraiment - une chaîne de sortie ne dépassant pas 75 caractères. Félicitations pour avoir compris le principe de programmation «ne faites pas ce que je dis, faites ce que je veux». Pour être complet, vous pouvez corriger le cas de coin de n <3 en ajoutant: si n> 2 sinon s [: n]
Dave
1
       >>> info = lambda data: len(data)>10 and data[:10]+'...' or data
       >>> info('sdfsdfsdfsdfsdfsdfsdfsdfsdfsdfsdf')
           'sdfsdfsdfs...'
       >>> info('sdfsdf')
           'sdfsdf'
       >>> 
Spouk
la source
1
Veuillez expliquer votre réponse?
Gwenc37
exemple similaire de cette fonction def info2 (data): if len (data)> 10: return data [: 10] + '...' else: return data instruction lambda de la conception sans nom dans un style fonctionnel ex = lambda x: x + 1 def ex (x): return x + 1
Spouk
1

Vous ne pouvez pas réellement "tronquer" une chaîne Python comme vous pouvez faire une chaîne C allouée dynamiquement. Les chaînes en Python sont immuables. Ce que vous pouvez faire est de découper une chaîne comme décrit dans les autres réponses, produisant une nouvelle chaîne contenant uniquement les caractères définis par les décalages et l'étape de découpage. Dans certains cas (non pratiques), cela peut être un peu ennuyeux, comme lorsque vous choisissez Python comme langue d'interview et que l'intervieweur vous demande de supprimer les caractères en double d'une chaîne en place. Doh.

Dave
la source
1
info = data[:min(len(data), 75)
Jesse
la source
Les réponses codées uniquement sont généralement considérées comme de faible qualité. Pourriez-vous ajouter une explication à votre réponse.
Lemon Kazi
0

Il n'y a pas besoin d'une expression régulière mais vous souhaitez utiliser le formatage de chaîne plutôt que la concaténation de chaîne dans la réponse acceptée.

C'est probablement la manière la plus canonique et Pythonique de tronquer la chaîne dataà 75 caractères.

>>> data = "saddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsaddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
>>> info = "{}..".format(data[:75]) if len(data) > 75 else data
>>> info
'111111111122222222223333333333444444444455555555556666666666777777777788888...'
Adam Nelson
la source
J'ai trouvé drôle la façon dont votre saddddddd...chaîne se transforme 111111...:) Je sais cependant que c'est une faute de copier-coller, et je suis d'accord avec vous sur les expressions régulières.
akarilimano
0

Voici une fonction que j'ai créée dans le cadre d'une nouvelle classe String ... Elle permet d'ajouter un suffixe (si la chaîne est de taille après l'ajustement et l'ajout est assez long - bien que vous n'ayez pas besoin de forcer la taille absolue)

J'étais en train de changer quelques choses autour donc il y a des coûts logiques inutiles (si _truncate ... par exemple) où ce n'est plus nécessaire et il y a un retour en haut ...

Mais, c'est toujours une bonne fonction pour tronquer les données ...

##
## 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
la source
1
ce qui est avec tous les soulignements dans chaque argument et variable unique?
Nicholas Hamilton
0
info = data[:75] + ('..' if len(data) > 75 else '')
Bonjour au revoir
la source