迭代list元素以获取特定数据

时间:2016-06-15 05:09:07

标签: python

我有以下数据,这是gedcom文件(家谱树数据文件)的一部分

0 @I4@ INDI
1 NAME Milo /Vettle/
2 GIVN Milo
2 SURN Vettle
2 _MARNM Vettle
1 SEX M
1 BIRT
2 DATE 23 OCT 1930
1 FAMS @F3@
0 @I5@ INDI
1 NAME Rosy /Huleknberg/
2 GIVN Rosy
2 SURN Huleknberg
2 _MARNM Vettle
1 SEX F
1 BIRT
2 DATE 15 SEP 1928
1 DEAT Y
2 DATE 10 MAR 2010

在上面的数据中,第一个数字是级别号,接下来是标签,下面的标签是参数。我将这些数据保存在列表中。现在,我想搜索'BIRT'标签,当程序点击时我想要打印下一行即出生日期。如果你注意到'DEAT'标签还有一个日期,但我想要日期,后面跟'BIRT'标签。

我怎样才能完成这项任务? 我试过了

  for line in list:
     if 'BIRT' in line:
        if 'DATE' in line:

          print line

3 个答案:

答案 0 :(得分:0)

使用示例代码编辑问题。这是一个解决方案,当在一行中遇到'BIRT'时设置触发器,并且只有在设置时,才输出一行中带有'DATE'的行。请注意,如果您还希望在“BIRT”行之后只需要直接,则必须稍微修改一下代码; - )

代码:

#! /usr/bin/env python
from __future__ import print_function

d = """
0 @I4@ INDI
1 NAME Milo /Vettle/
2 GIVN Milo
2 SURN Vettle
2 _MARNM Vettle
1 SEX M
1 BIRT
2 DATE 23 OCT 1930
1 FAMS @F3@
0 @I5@ INDI
1 NAME Rosy /Huleknberg/
2 GIVN Rosy
2 SURN Huleknberg
2 _MARNM Vettle
1 SEX F
1 BIRT
2 DATE 15 SEP 1928
1 DEAT Y
2 DATE 10 MAR 2010
"""

trigger_found = False
token_trigger = 'BIRT'
token_grep = 'DATE'

for line in d.split('\n'):
    if token_trigger in line:
        trigger_found = True
        continue
    if trigger_found and token_grep in line:
        print(line)
        trigger_found = False

使用Python v2.7.11进行测试:

2 DATE 23 OCT 1930
2 DATE 15 SEP 1928

与python v3相同。

注意:它可能也更强大(给出你的输入作为olny样本),触发像BIRT这样的标记(用空格填充,因为样本中给出的文本看起来可能有文本字段可能已被“输入”包含“代码”)如:

2 GIVN BIRTE

这是一个有效的名字。这不会改变此示例中的输出,但会无意中设置“触发器”。

更新(回答评论中的问题):

以上代码段中的这一行:

for line in d.split('\n'):

通过拆分换行符,在d中的文本块中创建一个列表。

如果您已经在列表foo中有一个行列表,比如因为从文件中读取或其他行,您可以改写:

for line in foo:

从文件中读取时,您经常会在“行”中包含换行字符,因此您经常会在for ...循环标题后看到s_line = line.strip()短,以摆脱那个以及周围的任何空白区域“想要那条线上的东西”。 HTH

更新:来自OP的好收获。答案中有一个拼写错误,写道:

if token_trigger and token_grep in line:

而不是正确的:

if trigger_found and token_grep in line:

这样,在成功打印想要的BIRTH DATE之后将触发器重置为False是没用的。

答案 1 :(得分:0)

以下是我一次性出现的东西,它不漂亮而优雅,但你可以用它作为参考来构建你自己的解决方案

def test():

    text = '''  0 @I4@ INDI
                1 NAME Milo /Vettle/
                2 GIVN Milo
                2 SURN Vettle
                2 _MARNM Vettle
                1 SEX M
                1 BIRT
                2 DATE 23 OCT 1930
                1 FAMS @F3@
                0 @I5@ INDI
                1 NAME Rosy /Huleknberg/
                2 GIVN Rosy
                2 SURN Huleknberg
                2 _MARNM Vettle
                1 SEX F
                1 BIRT
                2 DATE 15 SEP 1928
                1 DEAT Y
                2 DATE 10 MAR 2010'''
    lines = text.split('\n')

    tokens = [l.split(' ') for l in lines]

    tags = [token[1] for token in tokens]
    indices = [i for i, x in enumerate(tags) if x == 'BIRT']

    for i in indices:
        if tags[i+1] == 'DATE':
            print(lines[i+1])

<强>输出:

        2 DATE 23 OCT 1930
        2 DATE 15 SEP 1928

PS:tokens = [l.split(' ') for l in lines]假设空格是分隔符。如果事实并非如此,你可以改变它

<强>更新

鉴于您正在从文件中读取数据,您可以替换

lines = text.spilt('\n')

file = open('path_to_file')
lines = file.readlines()

然后在解决方案中继续使用相同的代码

答案 2 :(得分:0)

使用grep

$ grep -A1 '1 BIRT' so.txt | grep -E '^2'
2 DATE 23 OCT 1930
2 DATE 15 SEP 1928