2014-12-05 80 views
24

我必須訪問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) 
+2

是在代碼緊湊性方面「最佳」?可以做'行= [行閱讀器中的行]',然後'行[N]'。請注意,像其他一些答案一樣,這需要讀取整個文件。 – OJFord 2014-12-05 01:49:27

+1

這個問題似乎是無關緊要的,因爲它是關於工作代碼的優化,最適合於//codereview.stackexchange.com – Alex 2014-12-05 10:00:14

+0

正如Ollie所說,無論代碼是什麼樣子,你都從0的位置開始文件,並將位置x。這不像一個數組可以快速跳到正確的位置的數學。 – David 2014-12-05 10:46:31

回答

24

它沒有什麼區別,但它使用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]) 
+0

要使用'enumerate()'獲得行號,您可能需要將關鍵字參數'start = 1'添加到調用中。 – martineau 2014-12-05 13:59:15

+0

@martineau也許,但我已經離開它,因爲它是匹配從0開始的OP代碼。 – Stuart 2014-12-05 17:21:30

+0

啊,你說得對。根據更新我自己的答案。 – martineau 2014-12-05 17:35:32

3

你可以你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) 
6

您的解決方案其實並沒有那麼糟糕。推進文件迭代器到你想要的行是一個很好的方法,並在這樣的許多情況下使用。

如果你想讓它更簡潔,雖然,你可以使用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() 

在有如果未找到行究竟會返回NoneN太大) 。你可以選擇其他的值。


你也可以打開一個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)) 
+0

不錯的使用下!以前從未見過:-) +1 – Marcin 2014-12-05 01:45:48

6

你可以簡單地做:

import linecache 
n = 2 
linecache.getline('foo.csv', n) 
+1

代碼更緊湊,但對於小'n'更慢。 – OJFord 2014-12-05 01:48:09

+0

@OllieFord:謝謝你的觀察。 'linecache'可以用作替代。 – ajmartin 2014-12-05 01:57:29

+0

我不知道'linecache' - 這似乎是一個很好的解決方案! – OJFord 2014-12-05 01:59:14

3
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

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

甚至更​​好通過不加載整個文件到內存中使用較少的內存現在你可以通過它的獲得任何行directly

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

What line do you need? > 100 
This line does not exists 
+0

@Veedrac謝謝,我使用dict的基礎上它的O(1)複雜度爲d [k],但即使l [i]具有相同的O(1)複雜性。 – 2014-12-05 16:21:18

6

itertools該模塊可被用於創建專門迭代—及其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) 

P.S.對於好奇,我最初的反應—也可以工作(可以說是更好)—是:

row = next(itertools.islice(csv.reader(the_file), N, N+1)) 
+1

如果您確定CSV將源代碼行映射爲1:1的CSV行,請在將文件傳遞到'csv.reader'之前對文件進行切片('islice(infile,...)')。 – Veedrac 2014-12-05 13:06:23

+0

@Veedrac:非常好的點...更新。 – martineau 2014-12-05 13:27:49

+0

@Veedrac除了你沒有獲得任何東西,除了後面的錯誤數據的可能性...我會一直堅持原來的版本 – 2014-12-05 13:33:53

相關問題