6
votes

Tri du fichier texte en utilisant python

J'ai un fichier texte contient plus de 10 millions de lignes. Des lignes comme celle-là: xxx

comme vous l'avez vu, le délimiteur est ";". Je voudrais trier ce fichier texte à l'aide de Python selon le deuxième élément. Je ne pouvais pas utiliser la fonction scission. Parce que cela provoque MemeError. Comment puis-je le gérer?


11 commentaires

Pouvez-vous montrer le code que vous avez essayé?


Donc, vous dites que vous ne pouvez pas charger le fichier en mémoire?


C'est seulement environ 380 Mo de données. Courez-vous cela sur un téléphone?


@jordanm: double que lorsque vous utilisez un système d'exploitation 64 bits. 800 Mo pour un Python 64 bits 3.3 Build et l'OP permettent à Python décoder les données de fichier au lieu de le traiter comme binaire.


Si vous utilisez LIRE () et que vous lisez le fichier entier en mémoire, il s'agira d'une gamme de chaînes que pourrait remplir votre mémoire. Essayez de lire la ligne de fichier par ligne, en stockant un tuple de trois éléments de flotteurs / INTS. Cela devrait être beaucoup plus efficace de mémoire et vous pourrez peut-être vous faire pression sur votre mémoire.


@ Andrélaszlo: La chaîne (même en tant que données Unicode) prend moins d'octets, en fait. Les types de Python Int et de flotteur ont besoin d'un peu plus une fois converti.


@martjin Pouvez-vous élaborer? SYS.GETSIZEOF (37024469) -> 24 SYS.GETSIZEOF ("37024469") -> 48. Même les chaînes vides semblent prendre 40 octets, tandis que les entiers jusqu'à 10 ^ 18 prennent 24 octets. Évidemment, ces choses peuvent être spécifiques à la mise en œuvre.


@Martijnpieters: Vous avez complètement raison, bien sûr. Ma faute. Ma suggestion mange presque trois fois la mémoire :)


@george: Vous devez comparer une chaîne avec 2 entiers et une valeur de flotteur à la place.


Assez juste, mais si vous stockez uniquement des lignes entières telles que des chaînes, votre algorithme de tri devra analyser la chaîne à chaque fois qu'il a besoin de la valeur. Peut-être stocker des tuples de la forme (int (champ2), une chaîne entière) est optimale ..


@george: Il suffit d'analyser chaque ligne une fois de trier, de sorte que vous le permettez également pendant Tri: lignes.sort (clé = lambda l: int (l.split ( ';'; ', 2) [1])) .


3 Réponses :


22
votes

Ne triez pas 10 millions de lignes en mémoire. Diviser ceci en lots à la place:

  • Exécutez 100 traces de ligne 100K (à l'aide du fichier comme itérateur, associé à islice () code> ou similaire à choisir un lot). Écrire pour séparer les fichiers ailleurs. P> li>

  • fusionner les fichiers triés. Voici un générateur de fusion que vous pouvez passer 100 fichiers ouverts et donner des lignes dans la commande triée. Écrivez à une nouvelle ligne de fichier par ligne: p>

    import operator
    
    def mergeiter(*iterables, **kwargs):
        """Given a set of sorted iterables, yield the next value in merged order
    
        Takes an optional `key` callable to compare values by.
        """
        iterables = [iter(it) for it in iterables]
        iterables = {i: [next(it), i, it] for i, it in enumerate(iterables)}
        if 'key' not in kwargs:
            key = operator.itemgetter(0)
        else:
            key = lambda item, key=kwargs['key']: key(item[0])
    
        while True:
            value, i, it = min(iterables.values(), key=key)
            yield value
            try:
                iterables[i][0] = next(it)
            except StopIteration:
                del iterables[i]
                if not iterables:
                    raise
    


1 commentaires

Cette technique est également appelée tri externe .



1
votes

Vous pouvez le faire avec un os.System () appel à la fonction Bash Trier xxx


0 commentaires

5
votes

basé sur Tri d'un million Entier 32 bits en 2 Mo de RAM à l'aide de Python : xxx pré>

HASPQ.MERGE () CODE> a Paramètre CODE> depuis Python 3.5 . Vous pouvez essayer Mergeiter () Code> de Martijn Pieters 'Réponse à la place ou faire Transformer Schwartzian sur des versions plus anciennes Python: P>

$ python sort-k2-n.py < input.txt > output.txt


1 commentaires

HePq.Merge () sera ajouté à Python 3.5.