Ci sono almeno due possibilità:
array
Si potrebbe provare a utilizzare due array. Uno per le chiavi e uno per i valori in modo tale indice (chiave) == indice (valore)
Aggiornamento 2017-01-05: utilizza numeri interi a 4 byte nell'array.
Un array utilizza meno memoria. Su una macchina FreeBSD a 64 bit con python compilato con clang, una matrice di 30 milioni di interi utilizza circa 117 MiB.
Questi sono i comandi Python che ho usato:
Python 2.7.13 (default, Dec 28 2016, 20:51:25)
[GCC 4.2.1 Compatible FreeBSD Clang 3.8.0 (tags/RELEASE_380/final 262564)] on freebsd11
Type "help", "copyright", "credits" or "license" for more information.
>>> from array import array
>>> a = array('i', xrange(30000000))
>>> a.itemsize
4
Dopo l'importazione di array, ps
rapporti:
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
rsmith 81023 0.0 0.2 35480 8100 0 I+ 20:35 0:00.03 python (python2.7)
dopo aver effettuato la matrice:
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
rsmith 81023 29.0 3.1 168600 128776 0 S+ 20:35 0:04.52 python (python2.7)
The Resident Set Size è segnalato in 1 unità KiB, quindi (128776 - 8100)/1024 = 117 MiB
Con la comprensione delle liste è possibile ottenere facilmente un elenco di indici in cui la chiave soddisfa una determinata condizione. È quindi possibile utilizzare gli indici in tale elenco per accedere ai corrispondenti valori ...
NumPy
Se avete NumPy a disposizione, utilizzando tale è più veloce, ha un sacco più funzioni ed e usa un po 'meno RAM:
Python 2.7.5 (default, Jun 10 2013, 19:54:11)
[GCC 4.2.1 Compatible FreeBSD Clang 3.1 ((branches/release_31 156863))] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> a = np.arange(0, 30000000, dtype=np.int32)
Da ps
: 6700 KiB dopo l'avvio di Python, 17400 KiB dopo l'importazione NumPy e 134.824 KiB dopo aver creato l'array. Sono circa 114 MiB.
Inoltre, numpy supporta record arrays;
Python 2.7.5 (default, Jun 10 2013, 19:54:11)
[GCC 4.2.1 Compatible FreeBSD Clang 3.1 ((branches/release_31 156863))] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> a = np.zeros((10,), dtype=('i4,i4'))
>>> a
array([(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),
(0, 0), (0, 0)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
>>> a.dtype.names
('f0', 'f1')
>>> a.dtype.names = ('key', 'value')
>>> a
array([(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),
(0, 0), (0, 0)],
dtype=[('key', '<i4'), ('value', '<i4')])
>>> a[3] = (12, 5429)
>>> a
array([(0, 0), (0, 0), (0, 0), (12, 5429), (0, 0), (0, 0), (0, 0), (0, 0),
(0, 0), (0, 0)],
dtype=[('key', '<i4'), ('value', '<i4')])
>>> a[3]['key']
12
Qui è possibile accedere ai tasti e ai valori separatamente;
>>> a['key']
array([ 0, 0, 0, 12, 0, 0, 0, 0, 0, 0], dtype=int32)
Ci sono delle ipotesi si può fare WRT. i tasti? Per esempio. sono contigui? Sono entrati in ordine? Le prestazioni di ricerca O (lg n) sono accettabili? –
Gli oggetti Python sono piuttosto grandi, ma non credo che siano abbastanza grandi da far saltare in aria 30 milioni di coppie di numeri interi fino a 2 GB. Mi aspetterei di più nell'ordine di poche centinaia di megabyte. Come hai determinato quei numeri? E stai usando Python a 64 bit, o i tuoi interi sono particolarmente grandi (> diversi miliardi)? – delnan
Non so se questo è un suggerimento valido o no, ma considera l'utilizzo di un'altra lingua. Python è lento e consuma molta memoria. Considera C++ –