2016-03-07 38 views
0

我有一個看起來像這樣的一個示例文件:讀線的特定序列在Python

@XXXXXXXXX 
    VXVXVXVXVX 
    + 
    ZZZZZZZZZZZ 
    @AAAAAA 
    YBYBYBYBYBYBYB 
    ZZZZZZZZZZZZ 
    ... 

我希望只讀取落在指數4I + 2,其中i從0開始,所以線我應該閱讀上面代碼段中的VXVXV (4*0+2 = 2)...行和YBYB...(4*1 +2 = 6)行。我需要計算'V's, 'X's,'Y's and 'B's的數量並存儲在預先存在的字典中。

fp = open(fileName, "r") 
lines = fp.readlines() 

for i in xrange(1, len(lines),4): 
    for c in str(lines(i)): 
     if c == 'V': 
      some_dict['V'] +=1 

有人可以解釋我該如何避免離開索引,只讀取行列表中的4 * i + 2索引處的行?

+0

不幸的是,這不正確。 – newenthusiast

回答

2

難道你不能只切分行的列表?

lines = fp.readlines() 
interesting_lines = lines[2::4] 

編輯別人質疑它是如何工作:

「滿」片語法三個部分:start:end:step

start是起始索引,或者缺省值爲0。因此,對於4 * i + 2,當i == 0時,即索引2。

end是結束索引,或默認爲len(sequence)。切片上升至,但不包括最後一個索引。

step是所選項目之間的增量,默認爲1。通常,像3:7這樣的切片將返回元素3,4,5,6(和而不是 7)。但是,如果添加step參數,則可以執行「步驟4」等操作。

做「步驟4」意味着start+0, start+4, start+8, start+12, ...這是OP想要的,只要start參數選擇正確。

+0

在這種情況下,它是'lines [1 :: 4]',但是,這樣可以在不使用索引的情況下抓取所需的行。 – Ittociwam

+0

嘿,這比我的double-listcomp更合理。 +1 –

+0

工作就像一個魅力! @Ittociwam你能解釋一下這個切片如何轉化爲邏輯? – newenthusiast

0

您可以執行下列操作之一:

開始xrange在0,則在二次迴路加2到i

for i in xrange(0, len(lines), 4): 
    for c in str(lines(i+2)) 
     if c == 'V': 
      some_dict['V'] += 1 

開始xrange在2,然後訪問i在原來的計劃中規定的方式

for i in xrange(2, len(lines), 4): 
    for c in str(lines(i)) 
     if c == 'V': 
      some_dict['V'] += 1 
0

我不是很清楚你想在這裏做什麼 - - 你實際上只是想只讀取你想從磁盤讀取的行嗎? (在這種情況下,您從一開始就出錯了,因爲readlines()會讀取整個文件。)或者您只是試圖過濾行列表以挑選出想要的行?

我假設後者。在這種情況下,最簡單的事情就是使用listcomp來按索引過濾行。例如像這樣簡單:

indices = [x[0] * 4 + 2 for x in enumerate(lines)] 
filtered_lines = [lines[i] for i in indices if len(lines) > i] 

你去了,你只是想要的行,沒有索引錯誤或任何愚蠢的東西。然後,您可以分離出來並簡化剩餘的代碼來進行計數,只需對已過濾的列表進行操作即可。

(只是稍微改動過的第一個列表補償是一個小更地道)

+0

從技術上講,我只需要讀取4 * i + 2處的行,但爲了簡單起見,我只是爲了避免這種優化。我會嘗試這個listcomp。謝謝! – newenthusiast

+0

請注意幾個編輯---第一個listcomp現在更習慣了,第二個刪除了一個bug。 –

+0

這個listcomp不起作用:( – newenthusiast

-2

我已經給了類似的回答另一個問題:How would I do this in a file?

更好的解決方案(避免不必要的for循環)將

fp = open(fileName, "r") 
def addToDict(letter): 
    someDict[letter] += 1; 

[addToDict('V') for 'V' in str(a) for a in fp.readlines()[2::4]]; 

我試圖使這個匿名函數沒有成功,如果有人可以這樣做,它會很好。

+0

你可以解釋一下:[2 :: 4]? – newenthusiast

+0

爲什麼在對結果列表不感興趣的時候使用列表解析呢?另外,這個函數是完全不必要的。[somedict ['V'] + = 1 ...]'更加pythonic。這不能避免任何for循環,你只是看不到列表理解後面的for循環。在每次匹配時增加「V」的計數,而不是每行一次 – asdf

+1

Python將從索引2開始讀取列表,然後每隔四個元素讀取一次。它被稱爲切片。下面的示例與Numpy數組有關,但它也適用於常規列表:http://structure.usc.edu/numarray/node26.html – Wer900