Comment imprimer une chaîne de largeur fixe?

103

J'ai ce code (impression de l'occurrence de toutes les permutations dans une chaîne)

def splitter(str):
    for i in range(1, len(str)):
        start = str[0:i]
        end = str[i:]
        yield (start, end)
        for split in splitter(end):
            result = [start]
            result.extend(split)
            yield result    

el =[];

string = "abcd"
for b in splitter("abcd"):
    el.extend(b);

unique =  sorted(set(el));

for prefix in unique:
    if prefix != "":
        print "value  " , prefix  , "- num of occurrences =   " , string.count(str(prefix));

Je veux imprimer toutes les occurrences de permutation qu'il y a dans la chaîne varaible.

comme la permutation n'est pas de la même longueur, je veux fixer la largeur et l'imprimer dans un joli pas comme celui-ci:

value   a - num of occurrences =    1
value   ab - num of occurrences =    1
value   abc - num of occurrences =    1
value   b - num of occurrences =    1
value   bc - num of occurrences =    1
value   bcd - num of occurrences =    1
value   c - num of occurrences =    1
value   cd - num of occurrences =    1
value   d - num of occurrences =    1

Comment puis-je utiliser formatpour le faire?

J'ai trouvé ces articles mais cela ne s'est pas bien passé avec les chaînes alphanumériques:

format de chaîne python largeur fixe

Définition d'une longueur fixe avec python

0x90
la source
1
qu'en est-il de l'impression '% 10s'% 'mystring'
TJD
2
Surpris qui "\t"n'est répertorié comme une option dans aucune solution.

Réponses:

113

EDIT 2013-12-11 - Cette réponse est très ancienne. Il est toujours valide et correct, mais les personnes qui l'examinent devraient préférer la nouvelle syntaxe de format .

Vous pouvez utiliser un formatage de chaîne comme celui-ci:

>>> print '%5s' % 'aa'
   aa
>>> print '%5s' % 'aaa'
  aaa
>>> print '%5s' % 'aaaa'
 aaaa
>>> print '%5s' % 'aaaaa'
aaaaa

Fondamentalement:

  • le %personnage informe python qu'il devra remplacer quelque chose par un jeton
  • le scaractère informe python que le jeton sera une chaîne
  • le 5(ou le nombre que vous souhaitez) informe python de remplir la chaîne avec des espaces jusqu'à 5 caractères.

Dans votre cas spécifique, une implémentation possible pourrait ressembler à:

>>> dict_ = {'a': 1, 'ab': 1, 'abc': 1}
>>> for item in dict_.items():
...     print 'value %3s - num of occurances = %d' % item # %d is the token of integers
... 
value   a - num of occurances = 1
value  ab - num of occurances = 1
value abc - num of occurances = 1

REMARQUE: Je me suis simplement demandé si vous étiez conscient de l'existence du itertoolsmodule . Par exemple, vous pouvez obtenir une liste de toutes vos combinaisons sur une seule ligne avec:

>>> [''.join(perm) for i in range(1, len(s)) for perm in it.permutations(s, i)]
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'ba', 'bc', 'bd', 'ca', 'cb', 'cd', 'da', 'db', 'dc', 'abc', 'abd', 'acb', 'acd', 'adb', 'adc', 'bac', 'bad', 'bca', 'bcd', 'bda', 'bdc', 'cab', 'cad', 'cba', 'cbd', 'cda', 'cdb', 'dab', 'dac', 'dba', 'dbc', 'dca', 'dcb']

et vous pouvez obtenir le nombre d'occurrences en utilisant combinationsconjointement avec count().

Mac
la source
24
Vous devriez peut-être mentionner que les nombres négatifs donnent une sortie rembourrée justifiée à gauche; ce n'est guère intuitif pour un débutant.
tripleee
+1 pour @tripleee, sans vos nombres négatifs, donnez un commentaire justifié à gauche, j'aurais frappé ma tête plus longtemps ... thx m8.
Briford Wylie
C'est beaucoup plus intuitif et concis que le nouveau str.format. Je ne comprends pas pourquoi il y a cette poussée en python vers la convolution
scottmrogowski
Existe-t-il un moyen de remplir les espaces vides avec un caractère spécifique? Par exemple, si nous devons imprimer "05" au lieu de "5"
Harshit Jindal
1
Voici quelques astuces supplémentaires pour une impression élégante à largeur fixe avec des f-strings sur Medium .
pfabri du
198

Je trouve l'utilisation str.formatbeaucoup plus élégante:

>>> '{0: <5}'.format('ss')
'ss   '
>>> '{0: <5}'.format('sss')
'sss  '
>>> '{0: <5}'.format('ssss')
'ssss '
>>> '{0: <5}'.format('sssss')
'sssss'

Si vous souhaitez aligner la chaîne sur la bonne utilisation >au lieu de <:

>>> '{0: >5}'.format('ss')
'   ss'

Edit: Comme mentionné dans les commentaires: le 0 indique l'index de l'argument passé à str.format().

0x90
la source
5
De plus, le 0 indique la position de l'argument de format, vous pouvez donc faire deux autres choses: '{<5}'.format('ss') 'ss 'comme avant, mais sans le 0, fait la même chose ou 'Second {1: <5} and first {0: <5}'.format('ss', 'sss') 'Second sss and first ss 'vous pouvez réorganiser ou même afficher la même variable plusieurs fois dans une seule sortie chaîne.
mightypile
14
Je ne peux plus modifier le commentaire précédent, qui en a besoin. {<5}ne fonctionne pas, mais {: <5}fonctionne sans la valeur d'index.
mightypile
9
Voici le mini-langage de spécification de format Python décrivant ces chaînes de format et des options supplémentaires. Pour une référence rapide, l'espace dans {0: <5}est le [fill] , le <est [align]et 5est[width]
cod3monk3y
2
Ce 5 peut être une substitution de variable>>> print width 20 >>> print "{0: <{width}}".format("ssssss", width=width).split('\n') ['ssssss '] >>>
user2763554
4
Vous pouvez également utiliser des nombres et simplement lister les variables dans l'ordre width=10; "{0: <{1}}".format('sss', width). Ou même '{: <{}}'.format('sss', width)
omettez
72

Publié à l'origine en tant que modification de la réponse de @ 0x90, mais il a été rejeté pour avoir dévié de l'intention d'origine de la publication et recommandé de le publier en tant que commentaire ou réponse, j'inclus donc la courte description ici.

En plus de la réponse de @ 0x90, la syntaxe peut être rendue plus flexible, en utilisant une variable pour la largeur (selon le commentaire de @ user2763554):

width=10
'{0: <{width}}'.format('sss', width=width)

De plus, vous pouvez rendre cette expression plus brève, en utilisant uniquement des nombres et en vous basant sur l'ordre des arguments passés à format:

width=10
'{0: <{1}}'.format('sss', width)

Ou même omettre tous les nombres pour une compacité maximale, potentiellement non pythoniquement implicite:

width=10
'{: <{}}'.format('sss', width)

Mise à jour 26/05/2017

Avec l'introduction de chaînes littérales formatées ("f-strings" pour faire court) dans Python 3.6, il est désormais possible d'accéder à des variables précédemment définies avec une syntaxe plus brève:

>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'

Cela s'applique également au formatage des chaînes

>>> width=10
>>> string = 'sss'
>>> f'{string: <{width}}'
'sss       '
joelostblom
la source
J'aime vraiment cette réponse!
Syrtis Major
10

formatest certainement le moyen le plus élégant, mais afaik que vous ne pouvez pas l'utiliser avec le loggingmodule de python , alors voici comment vous pouvez le faire en utilisant le %formatage:

formatter = logging.Formatter(
    fmt='%(asctime)s | %(name)-20s | %(levelname)-10s | %(message)s',
)

Ici, le -indique l'alignement à gauche et le nombre avant sindique la largeur fixe.

Quelques exemples de sortie:

2017-03-14 14:43:42,581 | this-app             | INFO       | running main
2017-03-14 14:43:42,581 | this-app.aux         | DEBUG      | 5 is an int!
2017-03-14 14:43:42,581 | this-app.aux         | INFO       | hello
2017-03-14 14:43:42,581 | this-app             | ERROR      | failed running main

Plus d'informations dans la documentation ici: https://docs.python.org/2/library/stdtypes.html#string-formatting-operations

ryantuck
la source
Cependant, cela ne raccourcira pas les chaînes au-dessus de 20 caractères. Utilisez '%(name)20.20s'qui définit 20 à la fois comme longueur de chaîne minimale et maximale!
xjcl le
0
>>> print(f"{'123':<4}56789")
123 56789
Miladiouss
la source