过滤txt文件满足python中的某些条件?

问题描述 投票:0回答:1

我有一个包含subjectid_num_ [dog / cat] _ [option]的txt文件。

ID1_0123_CAT_ANIMAL_3
ID1_0123_CAT_ANIMAL_GOOD_3
ID1_0123_ABC_3
ID2_1234_CAT_ANIMAL_3
ID2_1234_CAT_ANIMAL_GOOD_3
ID2_1234_DOG_ANIMAL_2
ID2_1234_DOG_ANIMAL_GOOD_0
ID2_1234_ABCD_3
ID3_4321_DOG_ANIMAL_1
ID3_4321_DOG_ANIMAL_GOOD_4
ID3_4321_DOG_3

我想过滤文件以获得满足条件的输出。例如,下面的代码将在文件名中输出CATGOOD,并且名称中不包含DOGGOOD。该名称由相同的subject_id和相同的数字num决定。但是,代码不显示我的预期输出。我该如何解决?

这是我的代码

with open("./cat_dog.txt", 'r') as f:
    files_list = [line.rstrip('\n') for line in f]
file_filter = []
for i, cat in enumerate(files_list):
    if 'GOOD' in cat and 'CAT' in cat:
        subject_id = cat.split('_')[0]
        num_id = cat.split('_')[1]
        subject_num = subject_id + '_' + num_id
        for j, dog in enumerate(files_list):
                if subject_num in dog and 'GOOD' in dog:
                    if 'GOOD' in dog and 'DOG' in dog:
                        continue;
                    else:
                        file_filter.append(cat)

目前的输出是

ID1_0123_CAT_ANIMAL_GOOD_3
ID2_1234_CAT_ANIMAL_GOOD_3

虽然预期是

ID1_0123_CAT_ANIMAL_GOOD_3
python python-3.x
1个回答
1
投票

你的代码错了。考虑一下在内循环中检查行ID2_1234_CAT_ANIMAL_GOOD_3时会发生什么:

subject_id = cat.split('_')[0]            #ID2
num_id = cat.split('_')[1]                # 1234
subject_num = subject_id + '_' + num_id   #ID2_1234
for j, dog in enumerate(files_list):
        # when dog is the line ID2_1234_CAT_ANIMAL_GOOD_3
        if subject_num in dog and 'GOOD' in dog:   # this is true
            if 'GOOD' in dog and 'DOG' in dog:   # this is false
                continue;
            else:
                file_filter.append(cat)   # then it outputs it

问题是其中包含GOODCAT的每一行都将在内循环中“匹配”。

恕我直言,我会使用itertools.groupby。有点像:

from itertools import groupby

def key(line):
    return line.split('_')[:2]

for key, lines in groupby(sorted(files_list, key=key), key=key):
    good_lines = [line for line in lines if 'GOOD' in line]
    if len(good_lines) == 1 and 'CAT' in good_lines[0]:
        file_filter.append(good_lines[0])

这也应该是更有效的O(nlog n)vs O(n ^ 2),尽管它需要RAM中文件的所有内容。


如果你有除CATDOG以外的其他“类”并且你想输出所有GOOD CAT线,除非subject_id也是GOOD DOG你可以用这种方式修改上面的代码:

is_good_cat = any('CAT' in line for line in good_lines)
is_good_dog = any('DOG' in line for line in good_lines)
if is_good_cat and not is_good_dog:
    file_filter.extend(line for line in good_lines if 'CAT' in good_lines)

(你需要使用.extend和循环,因为我们不再知道哪一行是要写的,所以你必须过滤它们。

© www.soinside.com 2019 - 2024. All rights reserved.