Dezimalkommaausrichtungsmittel Formatierung in Python
-
06-07-2019 - |
Frage
Das sollte einfach sein.
Hier ist meine Array (besser gesagt, ein Verfahren zum Erzeugen von repräsentativen Testarrays):
>>> ri = numpy.random.randint
>>> ri2 = lambda x: ''.join(ri(0,9,x).astype('S'))
>>> a = array([float(ri2(x)+ '.' + ri2(y)) for x,y in ri(1,10,(10,2))])
>>> a
array([ 7.99914000e+01, 2.08000000e+01, 3.94000000e+02,
4.66100000e+03, 5.00000000e+00, 1.72575100e+03,
3.91500000e+02, 1.90610000e+04, 1.16247000e+04,
3.53920000e+02])
Ich möchte eine Liste von Strings, wo ‚\ n'.join (list_o_strings) würde drucken:
79.9914
20.8
394.0
4661.0
5.0
1725.751
391.5
19061.0
11624.7
353.92
Ich möchte Raum-Pad auf der linken Seite und das Recht (aber nicht mehr als nötig).
Ich mag eine Null hinter dem Komma, wenn das alles ist, dass nach dem Komma ist.
Ich will nicht die wissenschaftliche Notation.
.. und ich will keine signifikanten Stellen verlieren. (In 353,98000000000002 die 2 nicht signifikant)
Ja, es ist schön .. zu wollen
Python 2.5 des %g, %fx.x
usw. entweder befuddling mich, oder kann es nicht tun.
Ich habe nicht import decimal
noch versucht. Ich kann nicht sehen, dass NumPy tut es entweder (obwohl, sind die array.__str__
und array.__repr__
dezimal ausgerichtet ( aber manchmal wissenschaftliche zurück).
Oh, und die Geschwindigkeit zählt. Ich bin hier mit großen Arrays zu tun.
Meine aktuellen Lösungsansätze sind:
- auf str (a) und analysieren aus NumPy die Klammern
- str (e) jedes Element in dem Array und Split ( ''), dann Polster und Rekonstruieren
- a.astype ( 'S' + str (i)), wobei i der max (len (str (a))), dann Pad
Es scheint, wie es sollte da draußen einig off-the-shelf Lösung sein ... (aber nicht erforderlich)
Top Vorschlag nicht mit, wenn dtype
ist float64:
>>> a
array([ 5.50056103e+02, 6.77383566e+03, 6.01001513e+05,
3.55425142e+08, 7.07254875e+05, 8.83174744e+02,
8.22320510e+01, 4.25076609e+08, 6.28662635e+07,
1.56503068e+02])
>>> ut0 = re.compile(r'(\d)0+$')
>>> thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
>>> print '\n'.join(thelist)
550.056103
6773.835663
601001.513
355425141.8471
707254.875038
883.174744
82.232051
425076608.7676
62866263.55
156.503068
Lösung
Es tut uns Leid, aber nach gründlicher Untersuchung ich keinen Weg finden, können die Aufgabe, die Sie ohne ein Minimum an Nachbearbeitung erfordern auszuführen (um die nachgestellten Nullen abzustreifen Sie wollen nicht sehen); so etwas wie:
import re
ut0 = re.compile(r'(\d)0+$')
thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
print '\n'.join(thelist)
ist schnell und prägnant, aber bricht Ihre Einschränkung von „off-the-shelf“ zu sein - es ist vielmehr eine modulare Kombination der allgemeinen Formatierung (was fast tut, was Sie wollen, aber Blätter Hinter null Sie wollen sich verstecken) und eine RE unerwünschte nacheilenden Nullen zu entfernen. Praktisch, ich denke, es tut genau das, was Sie benötigen, aber Ihre Bedingungen wie angegeben sind, glaube ich, über eingeschränkt.
Bearbeiten : Original Frage bearbeitet wurde mehr signifikanten Stellen angeben, benötigt keinen zusätzlichen führenden Raum jenseits dem, was für die größte Zahl erforderlich ist, und bietet ein neues Beispiel (wo mein früherer Vorschlag, oben, doesn‘ t entsprechen den gewünschten Ausgang). Die Arbeit der führenden Leerzeichen entfernt werden, die zu einer Reihe von Zeichenketten üblich ist, wird am besten durchgeführt mit textwrap.dedent - aber das funktioniert auf einer einzigen Saite (mit Zeilenumbrüchen), während die erforderliche Ausgabe eine Liste von Strings ist. Kein Problem, wir werden nur die Linien zusammen, Dedent sie und verteilen sie wieder:
import re
import textwrap
a = [ 5.50056103e+02, 6.77383566e+03, 6.01001513e+05,
3.55425142e+08, 7.07254875e+05, 8.83174744e+02,
8.22320510e+01, 4.25076609e+08, 6.28662635e+07,
1.56503068e+02]
thelist = textwrap.dedent(
'\n'.join(ut0.sub(r'\1', "%20f" % x) for x in a)).splitlines()
print '\n'.join(thelist)
aussendet:
550.056103
6773.83566
601001.513
355425142.0
707254.875
883.174744
82.232051
425076609.0
62866263.5
156.503068
Andere Tipps
Pythons Zeichenfolge Formatierung beide können nur die notwendigen Dezimalstellen ausdrucken (mit% g) oder einen festen Satz von Dezimalstellen verwenden (mit% f). Sie möchten jedoch nur die notwendigen Dezimalstellen auszudrucken, mit der Ausnahme, wenn die Zahl eine ganze Zahl, dann wollen Sie eine Nachkommastelle, und das macht es kompliziert.
Dies bedeutet, dass Sie am Ende mit etwas würden wie:
def printarr(arr):
for x in array:
if math.floor(x) == x:
res = '%.1f' % x
else:
res = '%.10g' % x
print "%*s" % (15-res.find('.')+len(res), res)
Dies wird zunächst eine Zeichenfolge entweder mit 1 Nachkommastelle zu erstellen, wenn der Wert eine ganze Zahl ist, oder es wird mit automatischen Dezimalzahlen (aber nur bis zu 10 Nummern) drucken, wenn es nicht eine gebrochene Zahl ist. Schließlich wird es ausdrucken, so eingestellt, dass der Dezimalpunkt ausgerichtet werden.
Wahrscheinlich, aber numpy tatsächlich tut, was Sie wollen, weil Sie in der Regel es tun wollen, in der exponentiellen Modus sein, wenn es zu lang ist.