[Chapitre 2] Introduction à Python avec 100 coups de traitement du langage

Cet article est une suite de mon livre Introduction à Python avec 100 Language Processing Knock. Pour ceux qui veulent apprendre les bases de Python (et des commandes Unix) tout en travaillant sur 100 Knock Chapter 2.

Si vous pouvez atteindre le numéro 12, les bases de Python sont presque OK.

Après cela, je pense que vous sentirez que vous acquerrez progressivement un peu de connaissances détaillées. Tout d'abord, téléchargez le fichier spécifié dans l'énoncé du problème par une méthode appropriée.

$ wget https://nlp100.github.io/data/popular-names.txt

Supplément à l'énoncé du problème

Dans le traitement du langage naturel, il existe de nombreuses situations où vous souhaitez traiter un énorme fichier texte ligne par ligne, tout comme le problème dans ce chapitre.

TSV (valeurs séparées par des tabulations) et CSV (valeurs séparées par des virgules) sont souvent utilisés pour exprimer une structure dans laquelle une ligne est une donnée et les colonnes sont divisées en éléments. Les fichiers traités dans ce chapitre sont délimités par des tabulations, c'est donc TSV.

(Bien que cela prête à confusion, ces formats sont parfois appelés collectivement CSV (Character-Separated Values).)

Politique d'exemple de réponse

Les problèmes de ce chapitre utilisent pandas et la bibliothèque standard csv. Vous pouvez le résoudre, mais je n'en ressens pas tellement le besoin, alors je vais vous expliquer la méthode la plus simple. À propos, le style de codage de l'exemple de réponse suivra PEP8. Par exemple, le nom de la variable / le nom de la fonction doit être snake_case, et le retrait doit être de 4 espaces demi-largeur.

À propos des commandes Unix

Si vous n'êtes pas familier avec les options, les tuyaux, les redirections et less, veuillez lire les versets 1 et 3 de l'article Qiita ici. Vérifiez ensuite le contenu du fichier téléchargé avec $ less popular-names.txt.

Le nom de la commande est spécifié dans l'énoncé du problème, vous pouvez donc l'utiliser en utilisant pleinement --help sans le savoir. Cependant, la plupart des commandes Unix de ce chapitre sont courantes, alors gardez-les à l'esprit si vous le pouvez.

Lecture de fichier

En C, nous avons utilisé des pointeurs de fichier, mais en Python, nous utilisons un type de données pratique appelé objets de fichier. Les objets fichier sont itérables, donc si vous voulez lire un fichier texte ligne par ligne, écrivez:

with open('popular-names.txt') as f:
    for line in f:
        print(line, end='')

La syntaxe with est un excellent moyen de faire f = open ('popular-names.txt') et f.close () en quittant un bloc. La documentation officielle indique également qu'il s'agit d'une ** bonne pratique **, alors assurez-vous de l'utiliser.

Dans chaque boucle de l'instruction for, le contenu de chaque ligne est affecté à «line».

Pour utiliser plusieurs fichiers à la fois, utilisez des virgules comme with open ('test1') as f1, open ('test2') as f2.

Utilisez sys.stdin si vous voulez lire l'entrée standard ligne par ligne. C'est aussi un objet fichier. Tous les problèmes de ce chapitre peuvent être résolus de la manière ci-dessus, mais il est un peu plus pratique d'utiliser une entrée standard.

import sys

for line in sys.stdin:
    print(line, end='')
    

(Puisque l'entrée standard est ʻopen () depuis le début, veuillez penser que with` n'est pas nécessaire.)

(Certaines commandes Unix sont conçues pour accepter les entrées et les noms de fichiers standard, mais c'est un peu gênant de le faire avec Python → [Article de référence](https://qiita.com/hi-asano/items/ 010e7e3410ea4e1486cb)))

10. Compter le nombre de lignes

Comptez le nombre de lignes. Utilisez la commande wc pour confirmation.

Enregistrez le script Python, prenez popular-names.txt de l'entrée standard et exécutez-le.

Voici un exemple de réponse.

q10.py


import sys

i = 0
for line in sys.stdin:
    i += 1
print(i)

$ python q10.py < popular-names.txt
2780

Vous ne pouvez pas utiliser C ʻi ++ en Python, utilisez donc l'opérateur d'affectation cumulative + = `.

(Évitez f.read (). Splitlines (), f.readlines (), list (f) lorsque la taille du fichier est grande ou lorsque vous souhaitez effectuer un traitement compliqué.)

Je vais également aborder une méthode légèrement élégante. Il tire parti du fait que sys.stdin est itérable et que le bloc Python for ne forme pas de portée.

import sys


i = 0
for i, _ in enumerate(sys.stdin, start=1):
    pass

print(i)

La fonction intégrée ʻenumerate () qui compte le nombre de boucles est utile. C'est une convention Python pour recevoir les valeurs de retour inutilisées avec _. L'instruction pass` est utilisée lorsque vous ne voulez rien faire mais devez écrire quelque chose de grammaire.

Utilisez la commande wc (* nombre de mots *) pour confirmation. Si vous l'utilisez normalement, vous verrez différentes choses, alors spécifiez les options -l, --lines.

$ wc -l popular-names.txt
2780 popular-names.txt

11. Remplacez les onglets par des espaces

Remplacez chaque onglet par un espace. Utilisez la commande sed, la commande tr ou la commande expand pour confirmation.

Utilisons str.replace (ancien, nouveau). Cette méthode remplace la sous-chaîne ʻolddans la chaîne parnew` et la renvoie. Le caractère de tabulation est «\ t» comme en C.

Voici un exemple de réponse.

q11.py


import sys


for line in sys.stdin:
    print(line.replace('\t', ' '), end='')

Comme il y a beaucoup de lignes, vérifiez le résultat avec python q11.py <popular-names.txt | less etc.

Il y a trois commandes Unix répertoriées, mais sed -e's / \ t / / g'popular-names.txt est la plus populaire. Sur Twitter, je vois parfois des gens qui corrigent leurs fautes de frappe de cette façon avec des déchirures. sed signifie Stream EDitor et est une commande polyvalente.

Personnellement, la partie s / \ t / / g est gênante, alors devrais-je utiliser tr '\ t' '' <popular-names.txt ...

Cependant, sed est une commande que vous devez connaître, et vous pouvez utiliser sed -n 10p pour extraire la 10e ligne, sed -n 10, 20p pour extraire la 10e à la 20e ligne, etc. Pratique.

Écriture de fichier

Dans la question suivante, vous apprendrez à écrire des fichiers. Utilisez ʻopen (filename, 'w) `pour ouvrir un fichier texte en mode écriture.

with open('test', 'w') as fo:
    # fo.write('hoge')
    print('hoge', file=fo)

Vous pouvez utiliser la méthode write () lors de l'écriture, mais il est un peu gênant d'oublier d'ajouter un saut de ligne, donc je pense qu'il est préférable d'utiliser l'argument optionnel file de print ().

12. Enregistrez la première colonne dans col1.txt et la deuxième colonne dans col2.txt

Enregistrez la colonne extraite de chaque ligne sous col1.txt et la colonne extraite 2 sous col2.txt. Utilisez la commande cut pour confirmation.

Voici un exemple de réponse.

q12.py


import sys


with open('col1.txt', 'w') as fo1,\
     open('col2.txt', 'w') as fo2:
    for line in sys.stdin:
        cols = line.rstrip('\n').split('\t')
        print(cols[0], file=fo1)
        print(cols[1], file=fo2)

Cela aurait été bien d'écrire les deux ʻopen () ensemble sur une seule ligne, mais en utilisant la barre oblique inverse \ `on considère que l'instruction continue même si la ligne saute.

Vous pouvez utiliser ʻopen () pour lire popular-names.txt, mais je ne veux pas que l'instruction with` soit plus longue, donc j'utilise la méthode d'entrée standard.

La partie de line.rstrip ('\ n'). Split ('\ t') est appelée une chaîne de méthodes, et les méthodes sont exécutées dans l'ordre à partir de la gauche. Dans ce problème, le résultat ne change pas sans rstrip (), mais c'est pour empêcher cols [-1] d'inclure le caractère de saut de ligne. C'est un processus habituel lors de la lecture de texte.

Les commandes Unix sont OK si vous spécifiez les options -f, --fields dans cut. Vous pouvez exécuter la commande deux fois, mais vous pouvez le faire à la fois avec &&.

!cut -f1 popular-names.txt > col1.txt && cut -f2 popular-names.txt > col2.txt

13. Fusionnez col1.txt et col2.txt

Combinez les col1.txt et col2.txt créés dans 12 pour créer un fichier texte dans lequel les première et deuxième colonnes du fichier d'origine sont disposées en tabulation. Utilisez la commande coller pour confirmation.

C'est facile, non? Voici un exemple de réponse.

q13.py


with open('col1.txt') as fi1,\
     open('col2.txt') as fi2:
    for col1, col2 in zip(fi1, fi2):
        col1 = col1.rstrip()
        col2 = col2.rstrip()
        print(f'{col1}\t{col2}')

Writing q13.py

C'est là que la fonction intégrée «zip ()» entre en jeu. rstrip () supprime tous les sauts de ligne de fin et les blancs si l'argument est omis.

(Étant donné qu'il y aura 3 fichiers d'entrée ou plus, il est préférable de recevoir la valeur de retour de zip () comme une variable et join (). De plus, le comportement est plus proche de la commande paste. C'est difficile à essayer. Veuillez lire cet article.)

La commande Unix est OK avec paste col1.txt col2.txt.

14. Sortie de N lignes depuis le début

Recevoir le nombre naturel N au moyen d'un argument de ligne de commande et afficher uniquement les N premières lignes de l'entrée. Utilisez la commande head pour confirmation.

Les arguments de ligne de commande peuvent être obtenus avec sys.argv, mais il est un peu plus pratique d'utiliser ʻargparse`. Pour savoir comment l'utiliser, lisez le Grand Tutoriel Officiel depuis le début jusqu'aux "Options courtes" ...

Les tranches ne peuvent pas être utilisées car les objets fichier ne sont pas de type séquence. Comptons le nombre de lignes d'une autre manière.

Voici un exemple de réponse.

q14.py


import argparse
import sys


def arg_lines():
    parser = argparse.ArgumentParser()
    parser.add_argument('-n', '--lines', default=1, type=int)
    args = parser.parse_args()
    return args.lines


def head(N):
    for i, line in enumerate(sys.stdin):
        if i < N:
            print(line, end='')
        else:
            break


if __name__ == '__main__':
    head(arg_lines())
$ python q14.py -n 10 < popular-names.txt

La partie ʻargparseest transformée en une fonction indépendamment afin qu'elle puisse être réutilisée dans le problème suivant. ʻSi __name__ == '__ main __':empêche le processus principal d'être exécuté arbitrairement au moment de l'importation.

(Bruyant, ʻif name == '__ main __': `Ce n'est pas bon d'écrire un long processus ci-dessous, car toutes les variables sont globales. Python a un accès lent aux variables globales, donc les performances sont médiocres. Il y a aussi un inconvénient à ce que cela tombe en panne. En fait, ce sera légèrement plus rapide en transformant le code qui a été écrit solidement sans en faire une fonction.)

break est une instruction de contrôle utilisée dans le bloc for, et quitte immédiatement l'instruction for. N'oubliez pas avec continue (passez immédiatement à la boucle suivante).

La fonction head () peut être écrite un peu plus élégamment.

import sys
from itertools import islice

def head(N):
    for line in islice(sys.stdin, N):
        print(line, end='')

Les commandes Unix peuvent être head -n 5 popular-names.txt etc. Si vous omettez l'option, elle s'exécute avec la valeur par défaut (probablement 10).

Au moment de l'explication du n ° 11, j'ai écrit que le nombre de lignes est long, alors veuillez le passer à less avec un tuyau, mais si vous voulez vérifier uniquement le premier, head était suffisant.

Si vous passez ces commandes sur un tuyau, vous obtiendrez une Erreur de tuyau cassé à la fin. Si vous voulez éviter celahead popular-names.txt | python q11.pyComme en premierheadOu,python q11.py < popular-names.txt 2>/dev/null | headSupprimons la sortie d'erreur comme ceci.

15. Sortez les N dernières lignes

Recevoir le nombre naturel N au moyen d'un argument de ligne de commande et n'afficher que les N dernières lignes de l'entrée. Utilisez la commande tail pour confirmation.

Les objets fichier Python (les valeurs de retour de sys.stdin et ʻopen ()) ne peuvent faire avancer le pointeur de fichier que depuis le début (en principe). Il est inutile de compter le nombre de lignes une fois, puis de rouvrir le fichier. C'est une perte de mémoire de faire readlines ()` et de trancher le dos ...

Vous pouvez le faire intelligemment si vous connaissez la structure de données du premier entré, dernier sorti appelée * queue *. En d'autres termes, vous pouvez mettre le contenu du fichier ligne par ligne dans une file d'attente de longueur N. Ensuite, les éléments qui s'étendent au-delà de la longueur de la file d'attente sortiront sans autorisation, donc à la fin, seules les N dernières lignes resteront dans la file d'attente.

Utilisez le module deque dans le module collections pour implémenter les files d'attente en Python. Ou plutôt, la documentation officielle a un exemple de tail () dans la recette deque, qui est presque la réponse à cette question.

Voici un exemple de réponse.

q15.py


from collections import deque
import sys

from q14 import arg_lines


def tail(N):
    buf = deque(sys.stdin, N)
    print(''.join(buf))


if __name__ == '__main__':
    tail(arg_lines())

Le deque peut être tourné avec l'instruction for ainsi que la liste. Jusqu'à présent, la liste était tournée avec une instruction for vers print (), mais il est plus rapide dejoin ()etprint ()à la fois ([Reference](https: //). qiita.com/hi-asano/items/aa2976466739f280b887#%E3%81%8A%E3%81%BE%E3%81%91-%E5%95%8F%E9%A1%8C3-print)). Pour le numéro 14, print (''. Join (islice (sys.stdin, N)), end = '') suffisait.

Les commandes Unix sont OK avec tail -n 5.

Ci-dessous, le niveau de difficulté augmentera un peu, mais j'aimerais que vous le compreniez.

Iterable et itérateur

Dans l'article précédent, j'ai expliqué que "ce qui peut être tourné avec une instruction for s'appelle iterable". Ici, les types de données itérables (+ α) qui sont apparus jusqu'à présent peuvent être classés comme suit. Il n'est pas nécessaire de mémoriser les détails, mais il peut être plus facile de voir à quoi ils ressemblent lorsque vous rencontrez de nouveaux types de données à l'avenir.

Parlons maintenant de ** Iterator ** (que nous avions l'habitude de tricher et de gérer). Les types de données tels que les listes sont encombrants lorsqu'ils sont volumineux car tous les éléments sont stockés en mémoire à la fois. De plus, il y a beaucoup de gaspillage si vous n'avez pas besoin d'utiliser len () ou index et de l'utiliser simplement avec des arguments tels que l'instruction for oustr.join (). C'est une perte de temps de générer les éléments ultérieurs, surtout si vous n'avez pas besoin de boucler jusqu'au dernier élément. Les itérateurs ont éliminé ces inconvénients. Comme l'itérateur ne renvoie qu'un seul élément dans une boucle, il présente l'avantage de pouvoir gérer efficacement la mémoire. Vous ne pouvez pas utiliser de tranches, mais vous pouvez faire quelque chose comme ça avec ʻitertools.islice () . De plus, une fois la boucle complètement tournée, rien ne peut être fait. En raison de ces restrictions, il est utilisé exclusivement dans les instructions et les fonctions for` qui prennent des itérables comme arguments.

Les types de données qui prennent en charge non seulement les instructions «for» mais aussi les opérations «in» et «len ()» sont appelés collections ou conteneurs (bien qu'ils soient appelés conteneurs dans la documentation officielle, classe de base abstraite Par définition, les collections sont plus strictes).

Les index et les tranches peuvent être utilisés pour tous les types de séquence.

En plus de deque, le module collections définit des types de données utiles tels que Counter et defaultdict, donc soyez conscient de cela également. Peut être utilisé dans les prochains numéros.

Notation d'inclusion de liste et expression de générateur

Il y a des moments où vous souhaitez effectuer une opération sur tous les éléments d'un objet itérable un par un, ou lorsque vous souhaitez extraire uniquement les éléments qui remplissent les conditions. La notation d'inclusion et les expressions génératrices peuvent décrire ce traitement de manière concise. Prenons l'exemple de 100 coups 03 "rapport circonférentiel".

tokens = 'Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.'.split()

#Notation d'inclusion de liste
stripped_list = [len(token.rstrip('.,')) for token in tokens]
print(stripped_list)
[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

Tout d'abord, à partir de la notation d'inclusion de liste. Auparavant, c'était ʻappend () dans l'instruction for, mais dans la notation d'inclusion de liste, écrivez d'abord ce que vous voulez ʻappend () et attachez l'instruction for à la fin avec[]. Joindre. Cela peut être un peu difficile d'accès, mais cette façon d'écrire fonctionne plus rapidement ([Reference](https://qiita.com/hi-asano/items/aa2976466739f280b887#%E5%95%8F%E9%] A1% 8C1-% E3% 83% AA% E3% 82% B9% E3% 83% 88% E7% 94% 9F% E6% 88% 90)) Utilisez-le positivement.

Vient ensuite la formule du générateur. La valeur de retour du type de générateur est appelée type de générateur et est une sorte d'itérateur. L'itérateur ne peut être utilisé qu'en le tournant à nouveau avec l'instruction for ou en le passant à une autre fonction. Si quoi que ce soit, ce dernier est l'utilisation la plus courante.

#Type de générateur
stripped_iter = (len(token.rstrip('.,')) for token in tokens)

for token in stripped_iter:
    print(token, end=' ')
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 
' '.join(str(len(token.rstrip('.,'))) for token in tokens)
'3 1 4 1 5 9 2 6 5 3 5 8 9 7 9'

Comme vous pouvez le voir, l'expression du générateur vient de changer la notation d'inclusion de liste [] en (). Cependant, le () peut être omis lors du passage à l'argument de la fonction.

Le passage d'une expression de générateur à une fonction présente l'avantage de réduire les variables intermédiaires. Par rapport au passage d'une liste (notation inclusive), l'utilisation de la mémoire peut être réduite et les expressions génératrices sont souvent plus rapides.

(Dans de rares cas, il existe des fonctions qui sont plus rapides pour passer une liste, et ce join () semble être l'une des exceptions ...)

Fonction générateur

Le problème avec les expressions génératrices est qu'elles sont difficiles à écrire lorsque vous souhaitez effectuer un traitement compliqué. Vous souhaiterez peut-être définir une fonction qui renvoie un itérateur. Le moyen le plus simple est d'utiliser l'instruction yield, et celle définie de cette manière s'appelle la fonction générateur. Bien entendu, l'objet généré par la fonction générateur est également de type générateur.

Pour définir une fonction de générateur, placez la «valeur de retour de rendement» «au milieu» (ou à la fin) de l'opération de la fonction. La grande différence est que «return» termine le traitement de la fonction là-bas et les variables locales de la fonction disparaissent.

def tokens2lengths(tokens):
    for token in tokens:
        yield len(token.rstrip('.,'))

for token in tokens2lengths(tokens):
    print(token, end=' ')
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 

De quoi êtes-vous reconnaissant? C'est peut-être le cas ... Vous n'utiliserez pas la fonction générateur dans ces deux chapitres ... On dit qu'il sera plus facile d'écrire une fonction récursive, mais je n'écris pas beaucoup sur la fonction récursive elle-même ... Personnellement, je l'utilise dans les cas suivants. Tout d'abord, supposons que vous ayez votre propre fonction process.

for elem in lis:
    if elem is not None:
        outstr = process(elem)
        print(outstr)

Ce code ne rend pas fou le temps d'appel de la fonction car le nombre d'éléments dans lis augmente. Par conséquent, si le processus est converti en une fonction de générateur, il sera légèrement plus rapide. Vous pouvez également absorber l'expression conditionnelle et la fonction principale sera actualisée.

for outstr in iter_process(lis):
    print(outstr)

L'histoire qui n'est pas l'histoire principale est devenue longue. Résolvons le problème suivant.

Fluctuation des termes très détaillée

La documentation indique qu'un générateur fait généralement référence à une fonction de générateur et que l'objet généré par la fonction de générateur est appelé un itérateur de générateur. Cependant, si vous utilisez la fonction type () pour vérifier le type de retour de la fonction générateur (et de l'expression du générateur), vous verrez Generator. Pour cette raison, j'estime que l'itérateur officiel du générateur est souvent appelé générateur dans les documents non officiels.

16. Divisez le fichier en N

Recevez le nombre naturel N au moyen d'arguments de ligne de commande et divisez le fichier d'entrée en N ligne par ligne. Réalisez le même traitement avec la commande de fractionnement.

C'est un problème difficile. Il existe plusieurs méthodes possibles, mais il semble que la seule façon de briser la contrainte de ne pas mettre en mémoire le contenu du fichier à la fois est de compter d'abord le nombre total de lignes puis de le diviser. Vous pouvez rouvrir le fichier ou utiliser f.seek (0) (qui signifie faire référence aux 0 premiers octets) pour renvoyer le point de référence de l'objet fichier au début.

Et ** N diviser pour être aussi uniforme que possible est ennuyeux. Par exemple, si vous voulez diviser 14 lignes en 4 lignes, vous voulez les diviser en «4 lignes, 4 lignes, 3 lignes, 3 lignes». Pensons-y.

Si vous pouvez le faire, lisez et écrivez simplement 4 lignes. Il existe une méthode appelée fi.readline () qui ne lit qu'une seule ligne, mais c'est peut-être le tour. Vous devriez probablement écrire dans un fichier séparé.

Voici un exemple de réponse.

q16.py


import argparse
import sys


def main():
    parser = argparse.ArgumentParser(
        description='Output pieces of FILE to FILE1, FILE2, ...;')
    parser.add_argument('file')
    parser.add_argument('-n', '--number', type=int,
                        help='split FILE into n pieces')
    args = parser.parse_args()
    file_split(args.file, args.number)

    
def file_split(filename, N):
    with open(filename) as fi:
        n_lines = sum(1 for _ in fi)
        fi.seek(0)
        for nth, width in enumerate((n_lines+i)//N for i in range(N)):
            with open(f'{filename}.split{nth}', 'w') as fo:
                for _ in range(width):
                    fo.write(fi.readline())


if __name__ == '__main__':
    main()
$ python q16.py -n 3 popular-names.txt
$ wc -l popular-names.txt.split*
  926 popular-names.txt.split0
  927 popular-names.txt.split1
  927 popular-names.txt.split2
 2780 total

Vous n'avez pas à vous soucier de la façon d'utiliser ʻargparse. Pour compter le nombre de lignes, cette fois nous utilisons la fonction intégrée sum ()` pour calculer la somme des éléments de l'itérable.

Et comment diviser les nombres entiers uniformément. Supposons que le quotient est «q» et le reste est «r» lorsque vous divisez «m» éléments en «n» personnes. À ce moment, si vous distribuez normalement des pièces q à(nr)personnes et ajoutez un reste aux personnes r restantes et distribuez-les par (q + 1) pièces, ce sera pair. Je vais.

C'est la partie de ((n_lines + i) // N for i in range (N)) qui l'a écrit avec élégance. Vous pouvez tronquer et diviser le point décimal avec «//». Voir article Qiita ici pour voir pourquoi cela est également divisé.

Si vous ne vous souciez pas de l'ordre des lignes, vous pouvez utiliser tee () et ʻislice () de ʻitertools. Si vous ne vous souciez pas de la mémoire, il peut être plus facile d'utiliser zip_longest ().

La commande Unix doit être split -n l / 5 -d popular-names.txt popular-names.txt, mais cela peut ne pas fonctionner selon le split de votre environnement.

Le dernier problème est facile.

17. Différence dans la chaîne de caractères dans la première colonne

Recherchez le type de chaîne de caractères dans la première colonne (un ensemble de chaînes de caractères différentes). Utilisez les commandes sort et uniq pour confirmation.

Vous ajoutez simplement la première ligne à l'ensemble. Seule la notation d'inclusion de liste a été expliquée ci-dessus, mais il existe également une notation d'inclusion d'ensemble et une notation d'inclusion de dictionnaire.

Voici un exemple de réponse.

q17.py


import sys


names = {line.split('\t')[0] for line in sys.stdin}
print('\n'.join(names))

Gardez à l'esprit que le type d'agrégat change son ordre chaque fois qu'il est exécuté. Si vous n'aimez pas cela, utilisez le type de dictionnaire (implémentation CPython 3.6 ou version ultérieure, officiellement le type de dictionnaire 3.7 ou version ultérieure est dans l'ordre d'ajout de clé).

Commandes Unixcut -f1 popular-names.txt | sort | uniqSera.uniqPour supprimer les doublons dans les lignes adjacentes, procédez comme suitsortEst requis.

Expression et tri Lambda

Je vais l'utiliser pour le prochain problème, donc je suivrai l'expression lambda. Les expressions Lambda sont utilisées pour définir de petites fonctions. Par exemple, si vous écrivez lambda a, b: a + b, c'est une fonction qui renvoie la somme de deux nombres supplémentaires. Elle peut être appelée comme une fonction normale, mais elle est principalement utilisée comme argument optionnel de la fonction sort (). Pour le moment, il peut être passé à une autre fonction ou utilisé comme valeur de retour d'une fonction auto-créée.

Pour sort (), le [Sort HOW TO] officiel (https://docs.python.org/ja/3/howto/sorting.html) est une bonne ressource. Il suffit de lire jusqu'à "Ascendant et Descendant".

18. Triez chaque ligne dans l'ordre décroissant des nombres dans la troisième colonne

Disposez chaque ligne dans l'ordre inverse des nombres de la troisième colonne (Remarque: réorganisez le contenu de chaque ligne sans les changer) Utilisez la commande sort pour confirmation (ce problème ne doit pas nécessairement correspondre au résultat de l'exécution de la commande).

(Qu'est-ce qu'une colonne ... J'avais l'habitude de dire que j'étais en ligne ...) Voici un exemple de réponse.

q18.py


import sys


sorted_list = sorted(sys.stdin, key=lambda x: int(x.split('\t')[2]), reverse=True)
print(''.join(sorted_list))

Notez que les nombres de la troisième colonne resteront des chaînes à moins que vous ne les convertissiez en un type numérique. La diffusion peut être effectuée avec des fonctions intégrées.

La commande Unix est sort -k3 -nr popular-names.txt. Cela signifie que le troisième élément est considéré comme un nombre et trié par ordre croissant.

Unix sort est très bon et exécutera même des fichiers volumineux sans provoquer de manque de mémoire. Il est également relativement facile d'accélérer (peaufiner les paramètres régionaux, diviser et fusionner à la fin, etc.).

19. Recherchez la fréquence d'apparition de la chaîne de caractères dans la première colonne de chaque ligne et organisez-les par ordre décroissant de fréquence d'apparition.

Trouvez la fréquence d'apparition de la première colonne de chaque ligne et affichez-les par ordre décroissant. Utilisez les commandes cut, uniq et sort pour confirmation.

Ici, les lignes cachées de collections.Counter ont été récupérées! Si vous lisez la Documentation, il ne devrait y avoir aucun problème. Gardez à l'esprit que «Counter» est une sous-classe de «dict».

Voici un exemple de réponse.

q19.py


from collections import Counter
import sys


col1_freq = Counter(line.split('\t')[0] for line in sys.stdin)
for elem, num in col1_freq.most_common():
    print(num, elem)

Commandes Unixcut -f1 popular-names.txt | sort | uniq -c | sort -nrest. Lorsque les tuyaux sont connectés un par unheadJe pense que c'est une bonne idée de vérifier la sortie intermédiaire en utilisant.

Résumé

Vient ensuite le chapitre 3

Les fichiers JSON peuvent être lus avec le module json. Apprenez-en davantage sur les expressions régulières dans le Guide des expressions régulières J'écrirai une suite s'il y a LGTM ou des commentaires.

(Post-scriptum 4/30) L'explication du chapitre 3 a été publiée. → https://qiita.com/hi-asano/items/8e303425052781d95f09

Recommended Posts

[Chapitre 5] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 3] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 2] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 4] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 6] Introduction à scicit-learn avec 100 coups de traitement du langage
100 traitements de langage avec Python
100 traitements de langage avec Python (chapitre 2, partie 2)
100 coups de traitement du langage ~ Chapitre 1
Introduction au langage Python
Démarrer avec Python avec 100 coups sur le traitement du langage
100 coups de traitement du langage avec Python 2015
100 Language Processing Knock Chapitre 1 (Python)
100 Language Processing Knock Chapitre 2 (Python)
Réhabilitation des compétences Python et PNL à partir de "100 Language Processing Knock 2015" (Chapitre 1)
[Traitement du langage 100 coups 2020] Résumé des exemples de réponses par Python
Introduction au traitement parallèle distribué Python par Ray
J'ai essayé de résoudre la version 2020 de 100 problèmes de traitement du langage [Chapitre 3: Expressions régulières 20 à 24]
J'ai essayé de résoudre la version 2020 de 100 coups de traitement de langue [Chapitre 1: Mouvement préparatoire 00-04]
J'ai essayé de résoudre la version 2020 de 100 traitements linguistiques [Chapitre 1: Mouvement préparatoire 05-09]
100 traitements du langage naturel frappent le chapitre 4 Commentaire
[Traitement du langage 100 coups 2020] Chapitre 6: Machine learning
100 Language Processing Knock Chapitre 1 en Python
100 coups de traitement du langage 2020: Chapitre 4 (analyse morphologique)
[Traitement du langage 100 coups 2020] Chapitre 5: Analyse des dépendances
[Introduction à Python3 Jour 13] Chapitre 7 Chaînes de caractères (7.1-7.1.1.1)
[Introduction à Python3 Jour 14] Chapitre 7 Chaînes de caractères (7.1.1.1 à 7.1.1.4)
[Traitement du langage 100 coups 2020] Chapitre 1: Mouvement préparatoire
Traitement d'image avec la binarisation Python 100 knocks # 3
[Traitement du langage 100 coups 2020] Chapitre 7: Vecteur Word
[Introduction à Python3 Jour 15] Chapitre 7 Chaînes de caractères (7.1.2-7.1.2.2)
10 fonctions du "langage avec batterie" python
[Traitement du langage 100 coups 2020] Chapitre 8: Réseau neuronal
[Traitement du langage 100 coups 2020] Chapitre 2: Commandes UNIX
[Traitement du langage 100 coups 2020] Chapitre 9: RNN, CNN
100 traitement d'image par Python Knock # 2 Échelle de gris
100 Language Processing Knock Chapitre 1 par Python
[Traitement du langage 100 coups 2020] Chapitre 4: Analyse morphologique
[Introduction à Python3 Day 21] Chapitre 10 Système (10.1 à 10.5)
Traitement du langage 100 knocks-48: Extraction du chemin du nez à la racine
[Raspi4; Introduction au son] Enregistrement stable de l'entrée sonore avec python ♪
Réhabilitation des compétences Python et PNL à partir de «Knock 100 Language Processing 2015» (chapitre 2 deuxième semestre)
Réhabilitation des compétences Python et PNL à partir de "100 Language Processing Knock 2015" (Chapitre 2 premier semestre)
100 traitements linguistiques frappent 03 ~ 05
100 coups de traitement linguistique (2020): 40
Bases du traitement d'images binarisées par Python
100 coups de traitement linguistique (2020): 32
Résumé du chapitre 2 de l'introduction aux modèles de conception appris en langage Java
Système de notation IPynb réalisé avec TA d'introduction à la programmation (Python)
J'ai fait 100 traitements linguistiques Knock 2020 avec GiNZA v3.1 Chapitre 4
100 coups de traitement linguistique (2020): 47
[Introduction à Python3, jour 17] Chapitre 8 Destinations de données (8.1-8.2.5)
Chapitre 4 Résumé de l'introduction aux modèles de conception appris en langage Java
100 coups de traitement linguistique (2020): 22
100 traitement de langue knock-22: Extraction du nom de la catégorie
100 coups de traitement linguistique (2020): 26
100 coups de traitement linguistique (2020): 34
[Introduction à Python3, jour 17] Chapitre 8 Destinations de données (8.3-8.3.6.1)
100 coups de traitement linguistique (2020): 42
Introduction au remplissage d'image Python Remplissage d'image à l'aide d'ImageDataGenerator
Traitement du langage 100 coups Chapitre 4: Analyse morphologique 31. Verbes
Résumé du chapitre 3 de l'introduction aux modèles de conception appris en langage Java