2009-04-16 34 views
1

我有我已經存儲在列表中的一些數據,如果我打印出來的清單我看到以下內容:程序控制流量在Python

. 
. 
. 
007 A000000 Y 
007 B000000 5 
007 C010100 1 
007 C020100 ACORN FUND 
007 C030100 N 
007 C010200 2 
007 C020200 ACORN INTERNATIONAL 
007 C030200 N 
007 C010300 3 
007 C020300 ACORN USA 
007 C030300 N 
007 C010400 4 
. 
. 
. 

前和後序的點是代表還有其他類似結構的數據,但可能會或可能不會成爲第七項(007)的一部分。如果第七項中的第一個值是'007 A000000 Y',那麼我想創建一些數據項的字典列表。我可以做到這一點,只要遍歷列表中的所有項目,並將它們的值與變量的一些測試值進行比較即可。比如像一行代碼:

if dataLine.find('007 B')==0: 
    numberOfSeries=int(dataLine.split()[2]) 

我想,雖然做的是

if dataLine.find(''007 A000000 Y')==0: 
    READ THE NEXT LINE RIGHT HERE 

現在我不必通過整個列表遍歷每個週期

我想縮短處理,因爲我有大約60K的文件,每個文件有500到5000行。

我曾想過創建另一個列表引用並計數datalines直到dataLine.find(''007 A000000 Y')== 0。但是,這似乎並不是最優雅的解決方案。

+0

將最後一部分拆分爲答案!這是一個很好的問題,其他人可能會發現你想出了有用的東西:) – 2009-04-16 23:57:11

回答

0

好吧,當我在谷歌搜索,以確保我已經覆蓋了我的基地,我碰到一個解決方案:

我發現我忘了在列表和字典中思考,即使我使用它們。 Python有一些強大的工具來處理這些類型,以加速你操縱它們的能力。
我需要一個切片,因此切片引用由

beginPosit = tempans.index('007 A000000 Y') 
endPosit = min([i for i, item in enumerate(tempans) if '008 ' in item]) 

其中tempans是DataList控件 容易獲得,現在我可以寫

for line in tempans[beginPosit:endPosit]: 
    process each line 

我想我回答我自己的問題。我從其他答案中學到了很多東西,並且非常感謝他們,但我認爲這是我所需要的。

好吧,我要進一步編輯我的答案。我在這裏學到了很多東西,但其中一些東西已經超出了我的頭腦,並且我想了解一些代碼,而我正在學習更多關於這個神奇工具的知識。

from itertools import takewhile 
beginPosit = tempans.index('007 A000000 Y') 
new=takewhile(lambda x: '007 ' in x, tempans[beginPosit:]) 

這是基於早期的回答類似的問題和Steven Huwig's答案

+0

是的,但現在你正在通讀整個列表兩次,以找到你的切片索引 – kurosch 2009-04-17 19:18:47

2

您可以將數據讀取到字典中。假設你從一個類文件對象infile閱讀:

from collections import defaultdict 
data = defaultdict(list) 
for line in infile: 
    elements = line.strip().split() 
    data[elements[0]].append(tuple(elements[1:])) 

現在,如果你想閱讀後,「007 A000000 Y」行,你可以這樣做的:

# find the index of ('A000000', 'Y') 
idx = data['007'].index(('A000000', 'Y')) 
# get the next line 
print data['007'][idx+1] 
2

唯一的困難使用字典中的所有數據是一個真正的大字典會變得麻煩。 (這是我們習慣稱之爲「大奧萊矩陣」的方式。)

對此的解決方案是構建一個指數的詞典,創建的映射鍵 - >偏移,使用tell方法獲取文件偏移值。然後,您可以通過使用seek方法尋求再次參考該行。

3

您可以使用itertools.groupby()將您的序列分割成多個子序列。

import itertools 

for key, subseq in itertools.groupby(tempans, lambda s: s.partition(' ')[0]): 
    if key == '007': 
    for dataLine in subseq: 
     if dataLine.startswith('007 B'): 
     numberOfSeries = int(dataLine.split()[2]) 

itertools.dropwhile()也將工作,如果你真的只是想尋求到那個線,

list(itertools.dropwhile(lambda s: s != '007 A000000 Y', tempans)) 
['007 A000000 Y', 
'007 B000000 5', 
'007 C010100 1', 
'007 C020100 ACORN FUND', 
'007 C030100 N', 
'007 C010200 2', 
'007 C020200 ACORN INTERNATIONAL', 
'007 C030200 N', 
'007 C010300 3', 
'007 C020300 ACORN USA', 
'007 C030300 N', 
'007 C010400 4', 
'.', 
'.', 
'.', 
''] 
0

你說你想做到這一點:

if dataLine.find(''007 A000000 Y')==0: 
    READ THE NEXT LINE RIGHT HERE 

想必這是內部的「用於數據線數據「循環。

或者,你可以在使用迭代器,而不是直接的for循環:

>>> i = iter(data) 
>>> while i.next() != '007 A000000 Y': pass # find your starting line 
>>> i.next() # read the next line 
'007 B000000 5' 

你還別說有60K的文件進行處理。他們的格式都是相似的嗎?他們需要以不同的方式處理嗎?如果他們都可以處理同樣的方式,你可以考慮在一個單一的流鏈接在一起,其中:

def gfind(directory, pattern="*"): 
    for name in fnmatch.filter(os.listdir(directory), pattern): 
     yield os.path.join(directory, name) 

def gopen(names): 
    for name in names: 
     yield open(name, 'rb') 

def gcat(files): 
    for file in files: 
     for line in file: 
      yield line 

data = gcat(gopen(gfind('C:\datafiles', '*.dat'))) 

這讓你懶惰地處理在一個迭代器的所有文件。不知道這是否有助於你目前的狀況,但我認爲這值得一提。