1

以 IANA 的这种格式为例:http ://www.iana.org/assignments/language-subtag-registry

%%
Type: language
Subtag: aa
Description: Afar
Added: 2005-10-16
%%
Type: language
Subtag: ab
Description: Abkhazian
Added: 2005-10-16
Suppress-Script: Cyrl
%%
Type: language
Subtag: ae
Description: Avestan
Added: 2005-10-16
%%

假设我打开文件:

import urllib
f = urllib.urlopen("http://www.iana.org/assignments/language-subtag-registry")
all=f.read()

通常你会这样做

lan=all.split("%%") 

迭代局域网,split("\n")然后迭代结果和拆分(“:”),有没有办法在没有迭代的情况下在python中批量处理,输出仍然是这样的: [[["Type","language"],["Subtag", "ae"],...]...]

4

4 回答 4

3

如果您在每次拆分后获得的元素在语义上是不同的,那么我认为尝试一次执行此操作没有任何意义。

你可以先用“:”分割——这会让你得到细粒度的数据——但是,如果你不知道这些数据属于什么,那会有什么好处呢?

也就是说,您可以将所有级别的分离放在一个生成器中,并让它与您的数据一起生成字典对象,准备好使用:

def iana_parse(data):
    for record in data.split("%%\n"):
        # skip empty records at file endings:
        if not record.strip():
            continue
        rec_data = {}
        for line in record.split("\n"):
            key, value = line.split(":")
            rec_data[key.strip()] = value.strip()
        yield rec_data

它可以按照您在评论中的要求作为一个衬里来完成 - 但正如我评论的那样,它可以写成一行中的单个表达式。编写起来比上面的例子花费了更多的时间,而且几乎不可能维护。上面示例中的代码在几行代码中展开了逻辑,这些代码被放置在“不碍事的地方”——即不是内联实际数据的地方,为这两个任务提供了可读性和可维护性。

也就是说,可以根据需要将其解析为嵌套列表的结构:

structure = [[[token.strip() for token in line.split(":")] for line in record.split("\n") ] for record in data.split("%%") if record.strip() ]
于 2012-09-17T13:50:36.143 回答
3

作为一个单一的理解:

raw = """\
%%
Type: language
Subtag: aa
Description: Afar
Added: 2005-10-16
%%
Type: language
Subtag: ab
Description: Abkhazian
Added: 2005-10-16
Suppress-Script: Cyrl
%%
Type: language
Subtag: ae
Description: Avestan
Added: 2005-10-16
%%"""


data = [
     dict(
         row.split(': ')
         for row in item_str.split("\n")
         if row  # required to avoid the empty lines which contained '%%'
     )
     for item_str in raw.split("%%") 
     if item_str  # required to avoid the empty items at the start and end
]
>>> data[0]['Added']
'2005-10-16'
于 2013-09-10T10:17:22.513 回答
2

正则表达式,但我不明白这一点:

re.split('%%|:|\\n', string)

这里使用 or|运算符链接了多个模式。

于 2012-09-17T13:55:15.957 回答
2

您可以使用itertools.groupby

ss = """%%
Type: language
Subtag: aa
Description: Afar
Added: 2005-10-16
%%
Type: language
Subtag: ab
Description: Abkhazian
Added: 2005-10-16
Suppress-Script: Cyrl
%%
Type: language
Subtag: ae
Description: Avestan
Added: 2005-10-16
"""
sss = ss.splitlines(True) #List which looks like you're iterating over a file object


import itertools

output = []
for k,v in itertools.groupby(sss,lambda x: x.strip() == '%%'):
    if(k):  #Hit a '%%' record.  Need a new group.
        print "\nNew group:\n"
        current = {}
        output.append(current)
    else:   #just a regular record, write the data to our current record dict.
        for line in v:
            print line.strip()
            key,value = line.split(None,1)
            current[key] = value

这个答案的一个好处是它不需要您阅读整个文件。整个表达式被懒惰地评估。

于 2012-09-17T13:59:48.110 回答