Domanda

Questo dovrebbe essere facile.

Ecco il mio array (piuttosto un metodo per generare array di test rappresentativi):

>>> 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])

Voglio un elenco di stringhe in cui '\ n'.join (list_o_strings) stamperebbe:

   79.9914
   20.8
  394.0
 4661.0
    5.0
 1725.751
  391.5
19061.0
11624.7
  353.92

Voglio spaziare il pad a sinistra e a destra (ma non più del necessario).

Voglio uno zero dopo il decimale se questo è tutto ciò che è dopo il decimale.

Non voglio una notazione scientifica.

..e non voglio perdere cifre significative. (in 353.98000000000002 il 2 non è significativo)

Sì, è bello volerlo ..

% g,% fx.x di Python 2.5, ecc. mi stanno confondendo o non riescono a farlo. Non ho ancora provato import decimal . Non riesco a vedere che NumPy lo fa (sebbene, l'array .__ str __ e array .__ repr__ sono allineati con i decimali (ma a volte restituiscono dati scientifici).

Oh, e la velocità conta. Qui ho a che fare con grandi array.

I miei attuali approcci alla soluzione sono:

  1. per str (a) e analizzare le parentesi di NumPy
  2. per str (e) ogni elemento dell'array e dividere ('.') quindi pad e ricostruire
  3. a a.astype ('S' + str (i)) dove i è il massimo (len (str (a))), quindi pad

Sembra che ci dovrebbe essere qualche soluzione standard là fuori ... (ma non richiesta)

Il suggerimento principale fallisce quando dtype è 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
È stato utile?

Soluzione

Scusa, ma dopo un'indagine approfondita non riesco a trovare alcun modo per eseguire l'attività richiesta senza un minimo di post-elaborazione (per eliminare gli zeri finali che non vuoi vedere); qualcosa come:

import re
ut0 = re.compile(r'(\d)0+

è veloce e conciso, ma rompe il tuo vincolo di essere "pronto all'uso"; - è, invece, una combinazione modulare di formattazione generale (che fa quasi quello che vuoi ma lascia zero finale che vuoi nascondere) e un RE per rimuovere zeri finali indesiderati. In pratica, penso che faccia esattamente quello che richiedi, ma credo che le tue condizioni siano troppo limitate.

Modifica : la domanda originale è stata modificata per specificare cifre più significative, non richiede spazio aggiuntivo aggiuntivo oltre a quello richiesto per il numero più grande e fornisce un nuovo esempio (dove il mio suggerimento precedente, sopra, non t corrisponde all'output desiderato). Il lavoro di rimozione degli spazi bianchi principali che è comune a un gruppo di stringhe viene eseguito al meglio con textwrap.dedent - ma funziona su una singola stringa (con newline) mentre l'output richiesto è un elenco di stringhe. Nessun problema, metteremo insieme le linee, le dedicheremo e le divideremo di nuovo:

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)

emette:

      550.056103
     6773.83566
   601001.513
355425142.0
   707254.875
      883.174744
       82.232051
425076609.0
 62866263.5
      156.503068
) thelist = [ut0.sub(r'\1', "%12f" % x) for x in a] print '\n'.join(thelist)

è veloce e conciso, ma rompe il tuo vincolo di essere "pronto all'uso"; - è, invece, una combinazione modulare di formattazione generale (che fa quasi quello che vuoi ma lascia zero finale che vuoi nascondere) e un RE per rimuovere zeri finali indesiderati. In pratica, penso che faccia esattamente quello che richiedi, ma credo che le tue condizioni siano troppo limitate.

Modifica : la domanda originale è stata modificata per specificare cifre più significative, non richiede spazio aggiuntivo aggiuntivo oltre a quello richiesto per il numero più grande e fornisce un nuovo esempio (dove il mio suggerimento precedente, sopra, non t corrisponde all'output desiderato). Il lavoro di rimozione degli spazi bianchi principali che è comune a un gruppo di stringhe viene eseguito al meglio con textwrap.dedent - ma funziona su una singola stringa (con newline) mentre l'output richiesto è un elenco di stringhe. Nessun problema, metteremo insieme le linee, le dedicheremo e le divideremo di nuovo:

<*>

emette:

<*>

Altri suggerimenti

La formattazione della stringa Pythons può sia stampare solo i decimali necessari (con% g) o usare un set fisso di decimali (con% f). Tuttavia, vuoi stampare solo i decimali necessari, tranne se il numero è un numero intero, quindi vuoi un decimale e questo lo rende complesso.

Questo significa che finiresti con qualcosa del tipo:

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)

Questo prima creerà una stringa con 1 decimale, se il valore è un numero intero, oppure stamperà con decimali automatici (ma solo fino a 10 numeri) se non è un numero frazionario. Infine lo stamperà, regolato in modo che il punto decimale sia allineato.

Probabilmente, tuttavia, numpy in realtà fa quello che vuoi, perché in genere vuoi che sia in modalità esponenziale se è troppo lungo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top