Facile d'ignorer les lignes vides lors de la lecture d'un fichier en Python
J'ai un code qui lit un fichier de noms et crée une liste:
names_list = open("names", "r").read().splitlines()
Chaque nom est séparé par un saut de ligne, comme ceci:
Allman
Atkinson
Behlendorf
Je veux ignorer toutes les lignes qui ne contiennent que des espaces. Je sais que je peux le faire par la création d'une boucle et de vérifier chaque ligne j'ai lu et puis l'ajouter à une liste si elle n'est pas vide.
Je me demandais juste si il y avait une plus Pythonic moyen de le faire?
- Il n'y est une réponse ici: stackoverflow.com/questions/4791080/...
Vous devez vous connecter pour publier un commentaire.
Je pile générateur d'expressions:
Maintenant,
lines
est tous les non-lignes vides. Cela vous évitera d'avoir à appeler la bande sur la ligne deux fois. Si vous voulez une liste de lignes, vous pouvez le faire:Vous pouvez aussi le faire dans un one-liner (sauf
with
déclaration), mais ce n'est pas plus efficace et plus difficile à lire:Mise à jour:
Je suis d'accord que c'est laid en raison de la répétition de jetons. Vous pouvez simplement écrire un générateur si vous préférez:
Puis l'appeler comme:
mise à jour 2:
et sur Disponible (avec déterministe de comptage de référence)
En Python 2 utilisez
itertools.ifilter
si vous voulez un générateur et en Python 3, il suffit de passer le tout àlist
si vous voulez une liste.for line in lines
.filter
?()
aprèsl.strip
🙂nonblank_lines
fonction. Ce devrait être la première. Le reste est soit le code de golf ou un dévoreur de mémoire, car il se lit l'intégralité des fichiers dans une seule des listes (parfois) l'ensemble du fichier n'est pas nécessaire.nonblank_lines
générateur de fonction accomplit le filtre requis sans lire tout le fichier en mémoire.lines =...
instruction d'affectation ne peut pas être utilisé pour traiter les lignes une à une, car il doit lire l'intégralité du fichier dans un unique liste.lines=...
états -- tous -- doivent lire l'intégralité du fichier. Pas de choix. Pas de solutions de rechange. La définition de la fonction est complètement différent. Il peut être utilisé dans un contexte dans lequel chaque ligne est traitée séparé. Il a le choix. Il a des alternatives.lines =
avec pas de liste ou de filtre. Je comprends le point quelines = (...)
sera un générateur. Et je vois enfin la subtilité que j'ai eu tort. Je pense toujours que vous devez changer l'ordre de vos réponse.nonblank_lines()
de la fonction et de la(line.rstrip() for line in f_in)
sont DEUX générateur de fonctions. Je me suis trompé sur certainslines=
exemples. Certains deslines=
exemples sont générateur de fonctions qui ne sont pas de créer des listes de mémoire. Certains deslines=
exemples ne créer géant listes. Lenonblank_lines()
de la fonction et de la(line.rstrip() for line in f_in)
sont DEUX générateur de fonctions.lines=
avec et sanslist
, j'en ai un et un seul point. C'est, je préfère la fonction de la notation sur l'expression. C'est tout. J'ai été confondu par votre point de vue. Je ne suis plus confus. Je n'ai toujours rien beaucoup à dire. J'ai une préférence de la fonction sur l'expression. Que tout y est.Vous pouvez utiliser la liste de compréhension:
Mise à jour: Retiré inutile
readlines()
.Pour éviter l'appel de
line.strip()
deux fois, vous pouvez utiliser un générateur:Si vous le souhaitez, vous pouvez juste mettre ce que vous aviez dans une compréhension de liste:
names_list = [line for line in open("names.txt", "r").read().splitlines() if line]
ou
splitlines() a déjà retiré les fins de ligne.
Je ne pense pas que ceux qui sont aussi claires que juste en boucle explicitement que:
Edit:
Bien que, filtre semble tout à fait lisible et concis:
names_list = filter(None, open("names.txt", "r").read().splitlines())
Lorsqu'un traitement de texte doit être fait simplement en extraire des données, j'ai toujours penser d'abord à la regexes, parce que:
autant que je sache, regexes avoir été inventé pour que
itération sur les lignes apparaît maladroit pour moi: il consiste essentiellement à rechercher les retours à la ligne, puis de rechercher les données à extraire dans chaque ligne; cela fait deux recherches au lieu d'un seul avec une regex
façon de rassembler les regexes jouer, c'est facile; seulement l'écriture d'une expression rationnelle de la chaîne afin d'être compilées dans un objet regex est parfois dur, mais dans ce cas, le traitement avec une itération sur les lignes va être compliqué, trop
Pour le problème évoqué ici, une regex solution est rapide et facile à écrire:
J'ai comparé les vitesses de plusieurs solutions:
Solution avec la regex est simple et soigné. Cependant, il n'est pas parmi les plus rapides.
La solution de aaronasterling avec filtre() est surprisigly rapide pour moi (je n'étais pas au courant de ce filtre particulier()'s de vitesse) et les temps de solutions optimisées d'aller vers le bas jusqu'à 27 % de plus de temps. Je me demande ce qui fait le miracle du filtre-splitlines association:
Mais ce problème est particulier, le plus simple de tous: un seul nom dans chaque ligne. Si les solutions ne sont que des jeux avec des lignes, des splitings et [0:-1] les coupures.
Au contraire, la regex n'a pas d'importance avec les lignes, c'carrément trouve les données souhaitées: je considère que c'est une façon plus naturelle de la résolution, l'application des plus simples aux plus complexes, et par conséquent, est souvent le moyen d'être utilisés dans les traitements de textes.
MODIFIER
J'ai oublié de dire que j'utilise Python 2.7 et j'ai mesuré les temps ci-dessus avec un fichier contenant plus de 500 fois la chaîne suivante
[line for line in generator()]
, on pourrait simplement écrirelist(generator())
. Essayez de travailler avec des objets internes à chaque fois que possible. Ils sont écrits en C et tout le monde sait ce qu'ils font. Aussi, j'ai été appelerstr.rstrip
passtr.split
. Je ne sais pas si il y aura un gain de performance. Enfin,filter(None, ....)
est si rapide, car il est un condensé de toute la logique dans C.@S. Lott
Le code suivant traite les lignes une à une heure et produit un résultat qui n'est pas désireux de mémoire:
De sorte que le générateur de ligne.rstrip() à la ligne dans f_in) est tout à fait le même acceptable que la nonblank_lines() fonction.
Ce sujet LineSentence module, il va ignorer ces lignes:
Je pense qu'il y a une solution simple qui j'ai récemment utilisé après avoir donc beaucoup de réponses ici.
Cela fait exactement le même travail, en ignorant tous les vides de ligne.
Pourquoi êtes-vous tous d'aller à la dure?
Convertir non vides dans une liste si vous avez l'envie de le faire, bien que je vous suggère fortement de garder non vide d'un générateur comme il est en Python 3.x
En Python 2.x vous pouvez utiliser
itertools.ifilter
de faire votre appel d'offres à la place.