从字符串列表中,创建新列表,其中每个项指示原始列表中的相应项是否位于两个特定条目之间

2024-10-01 22:28:43 发布

您现在位置:Python中文网/ 问答频道 /正文

说我有这张单子

jay = ['Despite', 'similar', 'intensity', 'of', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', ',', 'ALC', '/', 'COC', 'subjects', 'received', 'less', 'oxazepam', 'to', 'treat', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', 'compared', 'to', 'ALC', 'subjects', '.']

我想做一个与原来的列表相对应的新列表。如果一个项目位于项目'<Disease:XXXXX>''</Disease:XXXXX>'之间,则第一个项目将被标记为“B-COL”,其余项目将被标记为“I-COL”。你知道吗

'<Disease:XXXXX>''</Disease:XXXXX>'本身没有任何标记。XXXX可以是数字范围。你知道吗

所有其他项目都被标记为“O”。你知道吗

下面是我想要的输出示例。你知道吗

idealOutput= ['O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O']

“疾病”标签对的数量可能会有所不同,这些标签之间的项目数量也会有所不同。你知道吗

以下是我的尝试:

wow = jay
labs = []
for i in range(0, len(wow)):
    if wow[i].startswith("<Disease"):
        labs.append('DelStrB')
    elif i>0 and i<=len(labs):
        if labs[i-1] == 'DelStrB':
            labs.append('B-COL')
            i = i + 1
            while not (wow[i].startswith("</Disease")):
                labs.append('I-COL')
                i = i + 1
            if wow[i].startswith("</Disease"):
                labs.append('DelStrE')
                i = i + 1
        elif wow[i].startswith("</Disease"):
            k=9 #do nothing
        else:
            labs.append('O')
    elif wow[i].startswith("</Disease"):
        k=9 #do nothing
    else:
        labs.append('O')

labs[:] = [x for x in labs if x != 'DelStrB']
labs[:] = [x for x in labs if x != 'DelStrE']

print(labs)

结果是

['O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-COL', 'O', 'O', 'O', 'O', 'O']

这是不正确的。我也知道有一种计算效率更高、更优雅的编码方式,但无法产生它。你知道吗


Tags: 项目in标记forifcolxxxxxlabs
3条回答

可以使用简单的生成器:

import re
jay = ['Despite', 'similar', 'intensity', 'of', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', ',', 'ALC', '/', 'COC', 'subjects', 'received', 'less', 'oxazepam', 'to', 'treat', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', 'compared', 'to', 'ALC', 'subjects', '.']
def results(d):
  _flag = -1
  for i in d:
    if re.findall('\<Disease:\w+\>', i):
      _flag = 1
    elif re.findall('\</Disease:\w+\>', i):
      _flag = -1
    else:
      if _flag == -1:
        yield 'O'
      elif _flag == 1:
        yield 'B-COL'
        _flag = 0
      else:
        yield 'I-COL'

print(list(results(jay)))

输出:

['O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O']

使用迭代方法的解决方案:

jay = ['Despite', 'similar', 'intensity', 'of', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', ',', 'ALC', '/', 'COC', 'subjects', 'received', 'less', 'oxazepam', 'to', 'treat', 'alcohol', '<Disease:D013375>', 'withdrawal', 'symptoms', '</Disease:D013375>', 'compared', 'to', 'ALC', 'subjects', '.']

result = []

inside = False
seen_BCOL = False

for i in range(len(jay)):
    if jay[i].startswith('<Disease'):
        inside = True
    elif jay[i].startswith('</Disease'):
        inside = False
        seen_BCOL = False
    elif inside == True:
        if seen_BCOL == False:
            result.append('B-COL')
            seen_BCOL = True
        else:
            result.append('I-COL')
    elif inside == False:
        result.append('O')


print(result)

['0', '0', '0', '0', '0', '0', 'B-COL', 'I-COL', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'B-COL', 'I-COL', '0', '0', '0', '0', '0', '0']

您可以使用itertools.groupby和一个查找“疾病”项的键函数,将列表分成奇数和偶数两组,以便使用不同的标记方法:

import re
from itertools import groupby
[t for i, l in enumerate(list(g) for k, g in groupby(jay, key=lambda s: re.match(r'</?Disease:\w+>', s)) if not k) for t in (('B-COL',) + ('I-COL',) * (len(l) - 1) if i % 2 else ('O',) * len(l))]

这将返回:

['O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-COL', 'I-COL', 'O', 'O', 'O', 'O', 'O']

请注意,预期的输出是不正确的,因为它在'B-COL''I-COL'的两个序列之间还有2个'O'

相关问题 更多 >

    热门问题