web-dev-qa-db-fra.com

Meilleur moyen d'accéder à la Nième ligne de fichier csv

Je dois accéder à la Nième ligne dans un fichier CSV.

Voici ce que j'ai fait:

import csv

the_file = open('path', 'r')
reader = csv.reader(the_file)

N = input('What line do you need? > ')
i = 0

for row in reader:
    if i == N:
        print("This is the line.")
        print(row)
        break

    i += 1

the_file.close()

... mais cela ne semble pas optimal. Modifier pour plus de précision: si le fichier est volumineux, je ne veux pas parcourir toutes les lignes et je ne veux pas avoir à charger tout le fichier en mémoire.

J'espère quelque chose comme reader[N] existe, mais je ne l'ai pas trouvé.

Modifier pour la réponse: Cette ligne (provenant de la réponse choisie) est ce que je cherchais:

next(itertools.islice(csv.reader(f), N, None)
28
Gabriel L'Heureux

Cela fait peu de différence mais il est légèrement plus propre d'utiliser enumerate plutôt que de créer votre propre variable de compteur.

for i, row in enumerate(reader):
    if i == N:
        print("This is the line.")
        print(row)
        break

Vous pouvez aussi utiliser itertools.islice qui est conçu pour ce type de scénario - accéder à une tranche particulière d'un itérable sans lire le tout en mémoire. Cela devrait être un peu plus efficace que de parcourir les lignes indésirables.

with open(path, 'r') as f:
    N = int(input('What line do you need? > '))
    print("This is the line.")
    print(next(itertools.islice(csv.reader(f), N, None)))

Mais si votre fichier CSV est petit, lisez simplement le tout dans une liste, à laquelle vous pouvez ensuite accéder avec un index de la manière habituelle. Cela présente également l'avantage que vous pouvez accéder à plusieurs lignes différentes dans un ordre aléatoire sans avoir à réinitialiser le lecteur csv.

my_csv_data = list(reader)
print(my_csv_data[N])
33
Stuart

Votre solution n'est en fait pas si mauvaise. Faire avancer l'itérateur de fichier jusqu'à la ligne souhaitée est une bonne approche et est utilisé dans de nombreuses situations comme celle-ci.

Si vous voulez que ce soit plus concis, vous pouvez utiliser next et enumerate avec un expression de générateur :

import csv

the_file = open('path', 'r')
reader = csv.reader(the_file)

N = int(input('What line do you need? > '))

line = next((x for i, x in enumerate(reader) if i == N), None)
print(line)

the_file.close()

Le None dedans est ce qui sera retourné si la ligne n'est pas trouvée (N est trop grande). Vous pouvez cependant choisir n'importe quelle autre valeur.


Vous pouvez également ouvrir le fichier avec un with-statement pour le fermer automatiquement:

import csv

with open('path', 'r') as the_file:
    reader = csv.reader(the_file)

    N = int(input('What line do you need? > '))

    line = next((x for i, x in enumerate(reader) if i == N), None)
    print(line)

Si vous voulez vraiment réduire la taille, vous pouvez faire:

from csv import reader
N = int(input('What line do you need? > '))
with open('path') as f:
    print(next((x for i, x in enumerate(reader(f)) if i == N), None))
7
iCodez

Vous pouvez simplement faire:

n = 2 # line to print
fd = open('foo.csv', 'r')
lines = fd.readlines()
print lines[n-1] # prints 2nd line
fd.close()

Ou encore mieux pour utiliser moins de mémoire en ne chargeant pas le fichier entier en mémoire:

import linecache
n = 2
linecache.getline('foo.csv', n)
6
ajmartin

Le module itertools a un certain nombre de fonctions pour créer des itérateurs spécialisés - et sa fonction islice() pourrait être utilisée pour résoudre facilement ce problème:

import csv
import itertools

N = 5  # desired line number

with open('path.csv', newline='') as the_file:
    row = next(csv.reader(itertools.islice(the_file, N, N+1)))

print("This is the line.")
print(row)

P.S. Pour les curieux, ma réponse initiale - qui fonctionne aussi (sans doute mieux) - a été:

    row = next(itertools.islice(csv.reader(the_file), N, N+1))
6
martineau
import csv
with open('cvs_file.csv', 'r') as inFile: 
    reader = csv.reader(inFile)
    my_content = list(reader)

line_no = input('What line do you need(line number begins from 0)? > ')
if line_no < len(my_content):
    print(my_content[line_no])
else:
    print('This line does not exists')

En tant que result, vous pouvez maintenant obtenir n'importe quelle ligne par son indexdirectly:

What line do you need? > 2
['101', '0.19', '1']

What line do you need? > 100
This line does not exists
3
Tanveer Alam

Vous pouvez minimiser votre boucle for en une expression de compréhension, par exemple.

row = [row for i,row in enumerate(reader) if i == N][0]  

# or even nicer as seen in iCodez code with next and generator expression

row = next(row for i,row in enumerate(reader) if i == N)
3
Marcin