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
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).)
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.
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.
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)))
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
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 par
new` 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.
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 ()
.
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
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
.
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.py
Comme en premierhead
Ou,python q11.py < popular-names.txt 2>/dev/null | head
Supprimons la sortie d'erreur comme ceci.
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.
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.
zip ()
, ʻenumerate () `list
, tuple
, str
, range
, colections.deque
set
, frozenset
(type d'agrégat immuable)
* Mapping
* dict
, collections.Counter
, collections.defaultdict
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.
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 ...)
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.
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.
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.
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 | uniq
Sera.uniq
Pour supprimer les doublons dans les lignes adjacentes, procédez comme suitsort
Est requis.
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".
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.).
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 -nr
est. Lorsque les tuyaux sont connectés un par unhead
Je pense que c'est une bonne idée de vérifier la sortie intermédiaire en utilisant.
str.replace()
argparse
collections
--Itérateur et générateurLes 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