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] ] 
4

5 に答える 5

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]

于 2012-06-12T13:04:52.690 に答える
1

おそらく次のようなものです:

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

varsは、このコードの実行後の値を格納するための単なる例['2', '7', '200']です (したがって、それらを float または int に変換する必要があります)。その後、これらを配列に追加するか、必要に応じて名前を変更できます。

EDIT:上記から派生した作業プログラム。

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
于 2012-06-12T13:05:43.630 に答える
0

構文についてはお答えできませんが、自己呼び出しを使用するのがおそらく最善です。

必要な行を検出し、バイト オフセットを格納する関数を記述します。次に、その関数自体を呼び出して次の行を見つけ(操作を終了する)、そのオフセットも保存し、以前に保存した値と比較します。

これで、変更が必要なバイトを特定するのに十分なデータが得られました。

ただし、自己呼び出し関数は、正しく使用すると非常に効率的であり、パフォーマンスが向上し、再利用が容易になります。

PHP では、このように動作する .net のものと同様のストリームライターを構築しました。したがって、理論が機能することはわかっていますが、これはpythonのようです。

残念ながら、私はその言語を十分に知りません。あなたのプロジェクトで頑張ってください!

于 2012-06-12T13:04:37.000 に答える
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. 変数 filename が「ファイル名」ではなく「ファイル」の場合は名前を付けないでください。
  2. for ループを使用して、行を 1 つずつループできます。
  3. split を使用して文字列を分割する
  4. startswith を使用して、文字列が別の文字列で始まるかどうかを確認します
  5. 変数の「*load」部分にいるかどうかを追跡します。

更新: open を関数名として使用しないでください。既に 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 : 多くのコメント:)

于 2012-06-12T13:06:53.623 に答える
-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]

これを大まかな提案としてコードとして使用してください...(例外は現在修正されていると思いますが、そうでない場合は気にしません...)

于 2012-06-12T13:04:51.217 に答える