Python:解析文本表并转换为嵌套数据结构

时间:2013-06-26 22:45:40

标签: python python-2.7

我需要解析一个具有以下格式的文本表:

-----------------------------------------
| Serial |     Name             | marks |
| Number |First | Middle | Last |       |
-----------------------------------------
| 1      | john |   s    |  doe |  56   |
| 2      | jim  |   d    |  bill|  60   |

解析表后,输出应该是一个嵌套字典,数据为列表。

TableData = {'Serial Number':[1,2], 
             'Name': {'First':[john, jim]} 
                     {'Middle':[s, d]} 
                     {'Last':[doe, bill]}
             'marks': [56, 60]
            }

截至目前,我有逻辑来获取分隔符(|)的位置,我可以在分隔符之间提取文本。

posList = [[0,9,32,40],[0,9,16,25,32]]
nameList = [['Serial','Name','marks'],['Number ','First','Middle','Last','  ']]

但是我很难将其转换为嵌套字典结构。

1 个答案:

答案 0 :(得分:4)

如果您知道数据结构应该是什么样的,那么您不能忘记前3行并从其余行中提取数据吗?例如,假设表位于文本文件table_file中,那么

table_data = {'Serial Number':[],
              'Name':{'First': [],
                      'Middle': []
                      'Last': []},
              'Marks': []}

with open(table_file, 'r') as table:
    # skip first 3 rows
    for _ in range(3):
        table.next()

    for row in table:
        row = row.strip('\n').split('|')
        values = [r.strip() for r in row if r != '']
        assert len(values) == 5
        table_data['Serial Number'].append(int(values[0]))
        table_data['Name']['First'].append(values[1])
        table_data['Name']['Middle'].append(values[2])
        table_data['Name']['Last'].append(values[3])
        table_data['Marks'].append(values[4])

修改 要构造table_data字典,请考虑以下伪代码。公平的警告,我测试了它,它似乎适用于你的例子,应该适用于任何有两行标题的东西。但是,它很草率,因为我在大约10分钟内写道。但是,它可以是一个可以开始改进和扩展的良好开端。这也假设您有用于提取pos_listname_list的代码。

for itertools import tee, izip
def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

def create_table_dict(pos_list, name_list):
    intervals = []
    for sub_list in pos_list:
        intervals.append(list(pairwise(sub_list)))

    items = []
    for interval, name in zip(intervals, name_list):
        items.append([ (i, n) for i, n in zip(interval, name) ])

    names = []
    for int1, name1 in items[0]:
        past_names = []
            for int2, name2 in items[1]:
        if int1[0] == int2[0]:
            if int1[1] == int2[1]:
                names.append(' '.join((name1, name2)).strip())
        elif int2[1] < int1[1]:
                past_names.append(name2)
        elif int1[0] < int2[0]:
            if int2[1] < int1[1]:
            past_names.append(name2)
            elif int1[1] == int2[1]:
            names.append('{0}:{1}'.format(name1, 
                                          ','.join(past_names + [name2])))

    table = {}
    for name in names:
        if ':' not in name:
            table[name] = []
        else:
            upper, nested = name.split(':')
            nested = nested.split(',')
            table[upper] = {}
            for n in nested:
                table[upper][n] = []

    print table