web-dev-qa-db-ja.com

csvファイルのN番目の行にアクセスする最良の方法

CSVファイルのN行目にアクセスする必要があります。

私がやったことは次のとおりです。

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()

...しかし、これは最適ではありません。正確さのための編集:ファイルが巨大な場合、すべての行を調べたくないので、ファイル全体をメモリにロードする必要はありません。

私はreader[N]は存在しますが、見つかりませんでした。

回答の編集:この行(選択した回答から)は、私が探していたものです:

next(itertools.islice(csv.reader(f), N, None)
28

違いはほとんどありませんが、独自のカウンタ変数を作成するのではなく、enumerateを使用する方が若干簡潔です。

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

このタイプのシナリオ向けに設計されたitertools.isliceを使用することもできます-全体をメモリに読み込まずに反復可能オブジェクトの特定のスライスにアクセスします。不要な行をループするよりも少し効率的です。

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)))

ただし、CSVファイルが小さい場合は、リスト全体を読み込んで、通常の方法でインデックスを使用してアクセスできます。これには、csvリーダーをリセットせずに、ランダムな順序で複数の異なる行にアクセスできるという利点もあります。

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

あなたのソリューションは実際にはそれほど悪くはありません。ファイルイテレータを目的の行に進めることは優れたアプローチであり、このような多くの状況で使用されます。

もっと簡潔にしたい場合は、 nextenumerategenerator expression とともに使用できます。

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()

そこのNoneは、行が見つからない場合に返されるものです(Nが大きすぎます)。ただし、他の値を選択できます。


with-statement でファイルを開いて、自動的に閉じることもできます:

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)

本当にサイズを削減したい場合は、次のことができます:

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

簡単にできます:

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

または、ファイル全体をメモリにロードしないことで、より少ないメモリを使用することもできます。

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

itertoolsmoduleには、特殊なイテレータを作成するための多くの関数があります。- islice() 関数を使用すると、この問題を簡単に解決できます。

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)

追伸好奇心For盛な人のために、私の最初の応答は-これも機能します(おそらくより良い)-は次のとおりです。

    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')

resultとして、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

forループを最小化して内包表記にできます。

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