Domanda

È possibile utilizzare numpy.memmap per mappareun grande array di stringhe basato su disco in memoria?

So che può essere fatto per float e simili, ma questa domanda riguarda specificamente le stringhe.

Sono interessato a soluzioni per stringhe di lunghezza fissa e variabile.

La soluzione è libera di dettare qualsiasi formato di file ragionevole.

È stato utile?

Soluzione

Se tutte le stringhe hanno la stessa lunghezza, come suggerito dal termine "array", questo è facilmente possibile:

a = numpy.memmap("data", dtype="S10")

sarebbe un esempio per stringhe di lunghezza 10.

Modifica : poiché apparentemente le stringhe non hanno la stessa lunghezza, è necessario indicizzare il file per consentire l'accesso all'elemento O (1).Ciò richiede la lettura dell'intero file una volta e l'archiviazione degli indici di inizio di tutte le stringhe in memoria.Sfortunatamente, non penso che esista un modo puro di indicizzazione NumPy senza creare prima un array delle stesse dimensioni del file in memoria.Tuttavia, questo array può essere eliminato dopo aver estratto gli indici.

Altri suggerimenti

L'opzione più flessibile sarebbe quella di passare a un database o ad una qualsiasi altra struttura di file su disco più complessa.

Tuttavia, probabilmente c'è una buona ragione per cui preferiresti mantenere le cose come un semplice file di testo ...

Poiché hai il controllo di come vengono creati i file, un'opzione è semplicemente scrivere un secondo file che contiene solo le posizioni di avviamento (in byte) di ciascuna stringa nell'altro file.

Questo richiederebbe un po 'più di lavoro, ma potresti essenzialmente fare qualcosa del genere:

class IndexedText(object):
    def __init__(self, filename, mode='r'):
        if mode not in ['r', 'w', 'a']:
            raise ValueError('Only read, write, and append is supported')
        self._mainfile = open(filename, mode)
        self._idxfile = open(filename+'idx', mode)

        if mode != 'w':
            self.indicies = [int(line.strip()) for line in self._idxfile]
        else:
            self.indicies = []

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self._mainfile.close()
        self._idxfile.close()

    def __getitem__(self, idx):
        position = self.indicies[idx]
        self._mainfile.seek(position)
        # You might want to remove the automatic stripping...
        return self._mainfile.readline().rstrip('\n')

    def write(self, line):
        if not line.endswith('\n'):
            line += '\n'
        position = self._mainfile.tell()
        self.indicies.append(position)
        self._idxfile.write(str(position)+'\n')
        self._mainfile.write(line)

    def writelines(self, lines):
        for line in lines:
            self.write(line)


def main():
    with IndexedText('test.txt', 'w') as outfile:
        outfile.write('Yep')
        outfile.write('This is a somewhat longer string!')
        outfile.write('But we should be able to index this file easily')
        outfile.write('Without needing to read the entire thing in first')

    with IndexedText('test.txt', 'r') as infile:
        print infile[2]
        print infile[0]
        print infile[3]

if __name__ == '__main__':
    main()
.

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