Disons que je dois systématiquement travailler avec des fichiers avec un nombre inconnu, mais grand, nombre de lignes. Chaque ligne contient un ensemble d'entiers (espace, virgule, point-virgule ou de caractère non numérique est le délimiteur) dans l'intervalle fermé [0, R], où R peut être arbitrairement grand. Le nombre d'entiers sur chaque ligne peut être variable. Souvent, je reçois le même nombre d'entiers sur chaque ligne, mais j'ai parfois des lignes avec des ensembles de nombres inégaux. P>
Supposons que je souhaite aller à la nième ligne dans le fichier et récupérer le numéro KTH sur cette ligne (et supposez que les entrées N et K sont valides - c'est-à-dire que je ne suis pas inquiet pour les mauvaises intrants). Comment puis-je faire cela efficacement dans Python 3.1.2 pour Windows? P>
Je ne veux pas traverser la ligne de fichier par ligne. P>
J'ai essayé d'utiliser du MMAP, mais tout en piquant ici, j'ai appris que ce n'est probablement pas la meilleure solution sur une construction 32 bits en raison de la limite de 4 Go. Et en vérité, je ne pouvais pas vraiment comprendre comment déplacer simplement N lignes de ma position actuelle. Si je peux au moins "sauter" à la nième ligne, je peux utiliser .split () et saisir le kth entier de cette façon. P>
Le nuance Voici que je n'ai pas seulement besoin de saisir une ligne du fichier. Je devrai saisir plusieurs lignes: ils ne sont pas nécessairement tous les uns des autres, l'ordre dans lequel je les obtiens, et la commande n'est pas toujours basée sur une fonction déterministe. P>
Des idées? J'espère que c'est assez d'informations. P>
merci! p>
3 Réponses :
Le problème est que, puisque vos lignes ne sont pas de longueur fixe, vous devez faire attention aux marqueurs d'extrémité de ligne pour effectuer votre recherche, et cela devient efficacement «traverser la ligne de fichiers par ligne». Ainsi, toute approche viable va toujours passer au dossier, il s'agit simplement d'une question de ce qui peut la traverser la plus rapide. P>
Supposons que je desserre la condition des lignes de longueur inégale. Par longueur, vous voulez dire le nombre réel de caractères ou le nombre d'entiers? Les fichiers les plus structurés que je vais obtenir sont ceux avec le même nombre d'entiers séparés par un délimiteur sur chaque ligne, mais ils n'auront pas nécessairement le même nombre de caractères. Est-ce que cela permet de faire ce dont j'ai besoin?
@Broivera, le problème est le nombre d'octets par ligne - comment ces octets d'une ligne sont divisés parmi des entiers ou tout autre chose est sans importance.
En supposant que ce soit des fichiers texte (et en supposant que le fichier est codé dans un codage de caractères à nombres fixe-de-numérotés, tels que l'ASCII uni), une "longueur égale" signifie un nombre égal de caractères. La raison pour laquelle cela fait une différence est parce que si vous savez que les lignes sont de longueur de caractère fixe i>, vous savez également que les lignes sont d'une longueur fixe d'octet i> longueur et donc Vous pouvez utiliser fichier.seek (Linelength * (linenum-1)) code> pour passer à l'octet qui commence une ligne donnée. Mais cela ne fonctionne que si linelength code> est le même pour toutes les lignes. Sinon, ce calcul est impossible.
+1 assez juste. Peut-être que ce que je suis sur le point de demander devrait être déplacé vers une autre question: ce que je reçois sont des fichiers texte avec codage ASCII. Je limiterai encore mes numéros à être compris entre [0, 2 ** 32 - 1]. Existe-t-il un format de fichier qui traitera chaque entiers comme la même taille? Ou existe-t-il un moyen de convertir mon fichier en un tel format? De cette façon, je pourrais utiliser le commandement .sek de la manière dont vous avez suggéré. Je comprends que cela augmentera ma taille de fichier. Mais je peux traiter avec ça.
Un format de fichier binaire qui représente des nombres comme des ensembles réels de 4 octets de 4 (32 bits) dans le fichier serait une largeur fixe (en supposant la même quantité de chiffres sur chaque ligne). La raison pour laquelle les chiffres du format ASCII ne sont pas une largeur fixe est que ASCII représente des nombres dans la base-10 alors qu'il est stocké dans un format binaire (base-2). Étant donné que la représentation diffère du stockage, la largeur n'est pas fixe. Bien sûr, une option serait de le forcer à être corrigée même en ASCII - par le remplissage de gauche des nombres avec des zéros afin que chaque nombre ait le même nombre de chiffres.
Oui, merci beaucoup pour vos suggestions! Malheureusement, je dois choisir une solution comme meilleure réponse. J'ai + 1'd comme toutes vos réponses!
's Si vous allez bien et je veux juste Caché de votre vue, alors la solution est le module de bibliothèque standard linecache - mais les performances ne seront pas meilleures que celles du code que vous pouvez vous écrire. p> Si vous devez lire à partir du même fichier grand fichier plusieurs fois, une grande optimisation serait de Exécutez une fois em> sur ce grand fichier un script qui construit et enregistre sur le disque de la correspondance de numéro de numéro de ligne - To-octet (techniquement un fichier auxiliaire "index"); Ensuite, toutes vos exécutions successives (jusqu'à ce que les gros changements de fichiers) puissent utiliser très rapidement le fichier d'index pour naviguer avec des performances très élevées via le grand fichier. Est-ce votre cas d'utilisation ...? P> puis pour l'utiliser, par exemple, le suivant recherche code> va à un octet em> décalse dans un fichier, non à une ligne em> décalage, simplement parce que c'est comme ça que c'est la façon dont les systèmes d'exploitation modernes et Leurs systèmes de fichiers fonctionnent - le système d'exploitation / FS n'enregistrez pas ou ne rappelez-vous pas de «compensations de ligne» de quelque manière que ce soit, et il n'y a aucun moyen pour Python (ni aucune autre langue) de les deviner magiquement. Toute opération prétendant "aller à une ligne" doit inévitablement "marcher dans le fichier" (sous les couvertures) pour rendre l'association entre les numéros de ligne et les décalages d'octets. makeindex.py code>, comme suit: p> utilindex .py code>: p> $ wc kjv10.txt
100117 823156 4445260 kjv10.txt
Votre solution d'optimisation est belle. je l'aime bien. +1. Je dois toujours traverser le fichier auxiliaire d'index cependant non? Mais bien sûr, c'est mieux que d'avoir à parcourir mon fichier d'origine. Linecache semble charger le fichier entier dans la RAM et je n'aurai pas toujours ce luxe.
@B Rivera, le "fichier auxiliaire d'index" doit être suffisamment petit pour rester en RAM, même pour un fil de texte de plusieurs millions de lignes. Permettez-moi d'esquisser une solution simpliste pour montrer ce que j'ai à l'esprit (je vais éditer ma réponse bientôt pour montrer que).
Vous savez quoi, je comprends ce que vous dites. Utilisez Linecache sur le fichier auxiliaire d'index. C'est certainement raisonnable.
Mieux encore, n'utilisez pas de format de texte pour votre index; Utilisez un format binaire avec des tailles de champs fixes. Ensuite, vous pouvez utiliser recherche () code> à ce sujet.
Une liste des compensations de 64 bits suffit pour que le fichier d'index autorise o (1) recherches
J'apprécie vraiment votre temps et votre réponse. Ceci est une solution générale viable.
@Amber, Yep - c'est ce que j'ai terminé en utilisant avec ma solution basée sur mon (code> (bien que la taille de l'élément de matrice pourrait être rare, en particulier depuis la lecture, je l'ai transformée en signé i> chiffres pour de simples buts de commodité).
@gnibbler, oui, et sur une construction de Python 32 bits Ma solution n'utiliserait que des compensations 32 bits, insuffisantes pour des fichiers vraiment volumineux (en particulier depuis que je les ai transformés en commodité, aka "Courses de coupe" ;-) . Il n'y a pas de moyen très pratique d'avoir un éventail de nombres entiers de 64 bits dans une construction 32 bits - je pourrais passer à 'd' code> (numéros de précision double offrant des fractions de 53 bits) ou prenez la Difficulté à enregistrer et à recharger chaque décalage comme deux i> de 22 bits.
@B Rivera, merci!, Mais pour la généralité, lisez mes 2 derniers commentaires sur la manière dont cela peut prouver que la limitation dans une version 32 bits (puisque les articles de la matrice ne seraient alors que 32 bits aussi) et des références sur des solutions possibles.
Une autre solution, si le fichier va potentiellement changer beaucoup, est de passer à tous vers une bonne base de données. Le moteur de base de données créera et maintiendra les index pour vous afin que vous puissiez effectuer des recherches / des requêtes très rapides. p>
Cela peut être un overkill cependant. P>
Je serais heureux s'il y avait une solution pour le cas lorsque j'ai le même nombre d'entiers sur chacun dans le fichier.