2015-10-07 34 views
5

私はフォーマットのこのタイプの行を含むファイルを持っているの複数の層で辞書に行を分割します。は、キーと値のペア

Example 1: 
nextline = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4 };" 

Example 2: 
nextline = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4; Player2 = 6; Player3 = 4 };" 

私は最初に行を ':'で分割し、2つのエントリを持つリストを表示します。 私は、キーと値を持つ辞書には、この行を分割したいのですが、スコアキーが値を持つ複数のサブキーを持っています。

Hole 1 
Par 4 
Index 2 
Distance 459 
Score 
    Player1 4 
    Player2 6 
    Player3 4 

だから私は、私はラインのscore要素にエラーが発生しますが、このような何か...

split_line_by_semicolon = nextline.split(":") 
dictionary_of_line = dict((k.strip(), v.strip()) for k,v in (item.split('=')  
    for item in split_line_by_semicolon.split(';'))) 
     for keys,values in dictionary_of_line.items(): 
      print("{0} {1}".format(keys,values)) 

を使用しています:

ValueError: too many values to unpack (expected 2) 

私は上の分割を調整することができます'=' これまで、それは最初の後に停止 '='

dictionary_of_line = dict((k.strip(), v.strip()) for k,v in (item.split('=',1)  
    for item in split_line_by_semicolon.split(';'))) 
     for keys,values in dictionary_of_line.items(): 
      print("{0} {1}".format(keys,values)) 

は、しかし、私は、中括弧内のサブ値を失います。誰も私がどのようにこの多層の辞書を達成することができるか知っていますか?

+0

'split_line_by_semicolon.split(「;」)'右側に私には見えません。 'split_line_by_semicolon'はリストで、リストは' split'メソッドを持っていません。これはあなたが実行しているコードとまったく同じですか? – Kevin

+0

正しい。私はそれの肉に得るために解析する行にいくつかの他のものがあります。だから、その実際には、[3] – John

答えて

2

それを行うための簡単な方法(しかし、それはあなたの状況で受け入れ可能であるならば、私は知りませんが)のようになります。

import re 

nextline = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4; Player2 = 6; Player3 = 4 };" 

# compiles the regular expression to get the info you want 
my_regex = re.compile(r'\w+ \= \w+') 

# builds the structure of the dict you expect to get 
final_dict = {'Hole':0, 'Par':0, 'Index':0, 'Distance':0, 'Score':{}} 

# uses the compiled regular expression to filter out the info you want from the string 
filtered_items = my_regex.findall(nextline) 

for item in filtered_items: 
    # for each filtered item (string in the form key = value) 
    # splits out the 'key' and handles it to fill your final dictionary 
    key = item.split(' = ')[0] 
    if key.startswith('Player'): 
     final_dict['Score'][key] = int(item.split(' = ')[1]) 
    else: 
     final_dict[key] = int(item.split(' = ')[1]) 
+1

感謝をsplit_line_by_semicolon。私はこれが好き。完璧にフィットします。 – John

0
lines = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4 };", "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4; Player2 = 6; Player3 = 4 };" 

def lines_to_dict(nextline): 
    import json 
    # cut up to Hole 
    nextline = nextline[nextline.index("Hole"):] 
    # convert to dict format 
    string_ = re.sub(r'\s+=',':',nextline) 
    string_ = re.sub(r';',',',string_) 
    # json likes double quotes 
    string_ = re.sub(r'(\b\w+)',r'"\1"',string_) 
    string_ = re.sub(r',$',r'',string_) 
    # make dict for Hole 
    mo = re.search(r'(\"Hole.+?),\W+Score.*',string_) 
    if mo: 
     d_hole = json.loads("{" + mo.groups()[0] + "}") 
    # make dict for Score 
    mo = re.search(r'(\"Score.*)',string_) 
    if mo: 
     d_score = json.loads("{" + mo.groups()[0] + "}") 
    # combine dicts 
    d_hole.update(d_score) 
    return d_hole 

for d in lines: 
pprint.pprint(lines_to_dict(d)) 

{'Distance': '459', 
'Hole': '1', 
'Index': '2', 
'Par': '4', 
'Score': {'Player1': '4'}} 

{'Distance': '459', 
'Hole': '1', 
'Index': '2', 
'Par': '4', 
'Score': {'Player1': '4', 'Player2': '6', 'Player3': '4'}} 
1

maccinzaが行ったように、私は同じように正規表現を使用します(私は彼の答えが好き)、1つのマイナーな違いが - それは再帰的に処理することが可能で、内部辞書とデータ:

#example strings: 
nextline1 = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4 };" 
nextline2 = "DD:MM:YYYY INFO - 'WeeklyMedal: Hole = 1; Par = 4; Index = 2; Distance = 459; Score = { Player1 = 4; Player2 = 6; Player3 = 4 };" 

import re 
lineRegexp = re.compile(r'.+\'WeeklyMedal:(.+)\'?') #this regexp returns WeeklyMedal record. 
weeklyMedalRegexp = re.compile(r'(\w+) = (\{.+\}|\w+)') #this regexp parses WeeklyMedal 

#helper recursive function to process WeeklyMedal record. returns dictionary 
parseWeeklyMedal = lambda r, info: { k: (int(v) if v.isdigit() else parseWeeklyMedal(r, v)) for (k, v) in r.findall(info)} 
parsedLines = [] 
for line in [nextline1, nextline2]: 
    info = lineRegexp.search(line) 
    if info: 
     #process WeeklyMedal record 
     parsedLines.append(parseWeeklyMedal(weeklyMedalRegexp, info.group(0))) 
     #or do something with parsed dictionary in place 

# do something here with entire result, print for example 
print(parsedLines) 
関連する問題