2012-06-12 27 views
0

我有下面的代碼至今:找到的代碼的某一塊文本

import sys 
from Tkinter import * 
import tkFileDialog 
from tkFileDialog import askopenfile # Open dialog box 


fen1 = Tk()        # Create window 
fen1.title("Optimisation")    # Window title 

menu1 = Menu(fen1) 

def open(): 
    filename = askopenfile(filetypes=[("Text files","*.txt")], mode='r') 

filename.seek(0) 
    numligne = 0 
    line  = [] 
    ok  = 0 
    k  = -1 

    while (ok == 0) & (k == -1): 
    line = filename.readline() 
    k = line.find("*load") 
    if k == 0 : 
     l = filename.readlines() 

fen1.mainloop() 

的文本文件,我正在尋找的格式爲類似於下面:

*test 
1 2 3 4 

*load 
2 7 200 
3 7 150 

*stiffness 
2 9 8 7 

etc.. 

我已經到目前爲止設法找到以「* load」開頭的行,但我希望將'* load'和'* stiffness'之間的值賦予變量,如a,b,c。我的問題是,在這個負載部​​分,可能有幾行,我需要每次檢測每一行,將行中的值分開並給它們起一個名字。如果有人可以請幫忙解釋一個循環或類似的東西,只會做這個伎倆,我會非常感激!謝謝!

更新:我有問題,現在我想在同一文本文件中找到幾個單獨的部分。我如何創建一個循環來進一步找到'* geo'和'* house'之間的連線,還有'* name'和'* surname'?我試圖創建一個完全獨立的定義,但想盡量減少我使用的代碼行......謝謝!代碼我一直在使用類似的結構(爲我的原始問題提供,感謝mgilson!),因此想要編輯這些類型的代碼。

def parse_file(ff):  
    out=[]  
    append=False  
    for line in ff:   
     if(append and line.strip()): 
      out.append(line)   
      if(line.startswith('*load')): 
       append=True 
      elif(line.startswith('*stiffness')): 
       return [map(int,x.split()) for x in out[:-1] ] 
+0

另外,是不是優化? – Digitalis

+0

@Digitalis如果你正在談論這個詞,'optimisation'是''優化'的法語。如果不是那麼,最有可能的是,因爲這是窗口標題所說的。 :P – jadkik94

+0

是的,我在英語和法語之間切換......因此,我現在在各種拼寫之間感到困惑.. – user2063

回答

1

讓我們假設你的「代碼塊」由標題分隔(例如*header)。在每個塊中存儲數據的最直觀的方式是列表列表。例如[ row1, row2, ...](其中row1=[elem1,elem2,elem3,...])。然後,您可以將該塊存儲在字典中,以便通過block=dictionary['headername']訪問該塊。

這將做類似你想要的東西(這個版本未經測試)。

import sys 

def convert_type(ss): 
    try: 
     return int(ss) 
    except ValueError: 
     try: 
      return float(ss) 
     except ValueError: 
      return ss 

def parse_file(ff): 
    out={} 
    block=None 
    for i,line in enumerate(ff): 
     #Allow for comments to start with '#'. We break off anything after a '#' 
     #and ignore it. After that, we 
     data=line.split('#',1) 
     line=data[0] #comments (if in line) are in data[1] ... ignore those. 
     line=line.strip() #remove whitespace from front and back of line. 
     if(line.startswith('*')): 
      #python supports multiple assignment. 
      #e.g. out['header'] is the same object as block. 
      #  changing block also changes out['header'] 
      block=out[line.strip()[1:]]=[] 
     elif (block is not None) and line: #checks to make sure there is an active block and the line wasn't empty. 
      #If the file could also have floats, you should use float instead of int 
      #We also put the parsing in a try/except block. If parsing fails (e.g. a 
      #element can't be converted to a float, you'll know it and you'll know the 
      #line which caused the problem.) 
      try: 
       #block.append(map(int,line.split())) 
       block.append(map(convert_type,line.split())) 
      except Exception: 
       sys.stderr.write("Parsing datafile choked on line %d '%s'\n"%(i+1,line.rstrip())) 
       raise 
    return out 

with open('textfile.txt','r') as f: 
    data_dict=parse_file(f) 

#get information from '*load' block: 
info=data_dict['load'] 
for row in info: 
    a,b,c=row 
    ##same as: 
    #a=row[0] 
    #b=row[1] 
    #c=row[2] 
    ##as long as row only has 3 elements. 

    #Do something with that particular row. 
    #(each row in the 'load' block will be visited once in this loop) 

#get info from stiffness block: 
info=data_dict['stiffness'] 
for row in info: 
    pass #Do something with this particular row. 

需要注意的是,如果你保證在數據文件中的每一行一定標題下具有相同數量的條目,你能想到的變量info爲2維的行被索引爲element=info[row_number][column_number]的 - - 但你也可以通過row=info[row_number]

+0

每行總是有3個數字,它是可以是隨機數的行數。 – user2063

+0

@ user20 - 好的,這很好理解,但重點是你想如何存儲數字?你想要1個列表嗎?或每行的列表?我的答案會爲每一行返回一個列表,但我不知道這是否合適。 – mgilson

+0

我相信每一行的列表會更合適,謝謝你的幫助=) – user2063

0

雖然我不能幫助你的語法,但最好使用自調試。

編寫一個函數來檢測你需要的行並存儲字節偏移量。 接下來,使該函數自己調用以查找下一行(結束操作),並存儲其偏移量並將其與以前保存的值進行比較。

現在您有足夠的數據來確定哪些字節需要更改。

但是,自我調用函數在使用時非常有效,它們加快了性能並且易於重用。

在php中,我建立了一個類似於.net的streamwriter,它以這種方式工作。 因此,我知道理論的作品,但是,這似乎是python。

不幸的是,我對這種語言不夠了解。雖然你的項目祝你好運!

+2

這是python格式錯亂:D – jadkik94

+0

注意到並編輯,謝謝:) – Digitalis

-2

這樣的事情應該做

data=[] 
check=false 
for i in fid: 
    if line.find("*load"): 
     check=true 
    if check==true and not line.find("*stiffness"): 
     line=split(i) 
     data.append(map(lambda x: float(x), line)) 
    if line.find("*stiffness"): 
     break 

fid.close() 
for i in data: 
    a=i[0] 
    b=i[1] 
    c=i[2] 

以此爲代碼粗糙的建議......(我想現在的例外是固定的,那麼,如果不是我不在乎......)

+1

我認爲你的'map'會在'* stiffness'行出現異常。 – mgilson

+0

是的...這只是一個粗略的建議,沒有測試 – Bort

+0

如果line.find(...)應該是'if line.find(...)== -1' – mgilson

1

也許這樣的事情讓整個行:

line = filename.readline() 
if line.find("*load") == 0: 
    line = filename.readline() 
    while line != "\n" and line != "": 
     vars = line.split(" ") 

vars僅僅是一個例子來存儲值這將是這個代碼運行後3210(所以你需要將它們轉換爲浮動或整數)。然後,您可以將這些附加到數組或根據需要重命名它們。

編輯:從上面得出的工作程序。

filename = open("fff.txt", 'r') 
values = {} 

line = filename.readline() 
while line: 
    while line.find("*") != 0: 
     line = filename.readline() 

    sectionheader = line.strip()[1:] 
    values[sectionheader] = [] 
    line = filename.readline() 
    while line != "\n" and line != "": 
     vals = [float(i) for i in line.split(" ")] 
     values[sectionheader].append(vals) 
     line = filename.readline() 

print values 
+0

'if line.find('* load'):'不起作用。當找到'* load'時,函數返回0(如果它是第一行) – mgilson

+0

哎呦,寫得太快,錯過了,修正了 – whrrgarbl

+0

我在這條線上仍然使用這個錯誤。 。 – user2063

0

這是我做你的代碼:

import sys 
from Tkinter import * 
import tkFileDialog 
from tkFileDialog import askopenfile # Open dialog box 


fen1 = Tk()        # Create window 
fen1.title("Optimisation")    # Window title 

menu1 = Menu(fen1) 

def do_open(interesting_parts=[]): 
    thefile = askopenfile(filetypes=[("Text files","*.txt")], mode='r') 

    data = {} # Create a dictionary to store all the data stored per part name 
    part = None 
    for line in thefile: 
     if line.startswith("*"): 
      # A * in the beginning signals a new "part" 
      # And another one means the end. 
      part = line[1:] # Remove the * in the beginning via slicing to get the name without it. 
      if part in interesting_parts: 
       data[part] = [] # Create a list inside the dictionary, so that you can add data to it later. 
       # Only do this if we are interested in storing anything for this part 
     elif part in interesting_parts: 
      # Add an a condition to check if the part name is in the list of "parts" you are interested in having. 
      line_data = get_something_from_this(part, line) # just a function that returns something based on the line and the part 
      if line_data is not None: # Ignore it if it's None (just an option, as there might be newlines that you want to ignore) 
       data[part].append(line_data) 

    # Here, we return the dictionary to act on it. 
    return data 

def get_something_from_this(part, line): 
    try: 
     ints = [int(p) for p in line.split()] 
    except ValueError: 
     print "Ignoring Line", repr(line), "in", part 
     return None # We don't care about this line! 
    else: 
     print "in", part, ints 
     return ints # Store this line's data 

data = do_open(["test", "egg"]) # Pass as an argument a list of the interesting "parts" 

print data # this is a dictionary 

# How do you access it? 
print data["test"] # to get all the lines' data in a list 
print data["egg"][0] # to get the first line of the data 

for part, datalines in data.iterkeys(): 
    print part, datalines # datalines is the list of all the data, part is the dictionary's key which is the part name 
    # Remember data[part] = ... <- Here part is the key. 

fen1.mainloop() 
  1. 時,它不是一個「文件名」,而是一個「文件」不要將其命名變量名。
  2. 您可以使用for循環逐行循環。
  3. 使用拆分拆分字符串
  4. 使用startswith知道,如果一個字符串與另一個字符串開頭的你是否正處在一個變量「*負荷」部分
  5. 跟蹤。

UPDATE: 不要使用開放作爲一個函數的名稱,它已經在Python的內置命令。 此外,爲了避免解析*load*stiffness行,我修改了一下代碼:每行的解析都在elif語句中完成。

更新2:根據OP的需求

更新後的代碼。

*test 
1 2 3 

*load 
2 7 200 
3 7 150 

*stiffness 
2 9 8 

*egg 
1 2 3 
2 4 6 

*plant 
23 45 78 

更新3:這個文件測試的大量註釋:)

+0

我只是使用'line.split()'而不是'line.split(「」)'(它們細微的不同)。但是,將所有數據存儲在字典中的確是實現這一目標的方法。 (這也是我最終爲編輯做的)。 – mgilson

+0

我真的很喜歡這種方法,但對於我可以在哪裏分配找到的變量值以及如何找到某些部分有些困惑。例如,如果我只是想找到*測試和*蛋。 – user2063

+0

@mgilson很高興知道這有什麼不同......我想我會讓它更加明確。 – jadkik94