如何根据多个条件过滤列表?

时间:2019-11-25 21:38:44

标签: python list

我有以下列表:

req.query.uuid

target_list = ["FOLD/AAA.RST.TXT"]

如何仅过滤与mylist = [ "FOLD/AAA.RST.12345.TXT", "FOLD/BBB.RST.12345.TXT", "RUNS/AAA.FGT.12345.TXT", "FOLD/AAA.RST.87589.TXT", "RUNS/AAA.RST.11111.TXT" ] 相对应的mylist记录?预期结果是:

target_list

考虑使用以下掩码过滤 "FOLD/AAA.RST.12345.TXT" "FOLD/AAA.RST.87589.TXT"

mylist

如果xxx/yyy.zzz.nnn.txt xxxyyyzzz一致,则应选择记录。否则应将其从结果中删除。

如何使用for循环解决此任务?

target_list

4 个答案:

答案 0 :(得分:2)

您可以定义用于预处理目标列表的“过滤器制作功能”。这样做的优点是:

  • 通过在集合中缓存有关target_list的信息来进行最少的工作:总时间为O(N_target_list) + O(N),因为集合查找平均为O(1)。
  • 不使用全局变量。易于测试。
  • 不使用嵌套的循环
def prefixes(target):
    """ 
    >>> prefixes("FOLD/AAA.RST.TXT")
    ('FOLD', 'AAA', 'RST')

    >>> prefixes("FOLD/AAA.RST.12345.TXT")
    ('FOLD', 'AAA', 'RST')
    """
    x, rest = target.split('/')
    y, z, *_ = rest.split('.')
    return x, y, z

def matcher(target_list):
    targets = set(prefixes(target) for target in target_list)
    def is_target(t):
        return prefixes(t) in targets
    return is_target

然后,您可以这样做:

>>> list(filter(matcher(target_list), mylist))
['FOLD/AAA.RST.12345.TXT', 'FOLD/AAA.RST.87589.TXT']

答案 1 :(得分:1)

定义一个用于过滤值的函数:

target_list = ["FOLD/AAA.RST.TXT"]

def keep(path):
    template = get_template(path)
    return template in target_list

def get_template(path):
    front, numbers, ext = path.rsplit('.', 2)
    template = '.'.join([front, ext])
    return template

这使用str.rsplit进行反向搜索,然后将其分割为给定字符.。参数2表示最多只能执行两个拆分。这给了我们三个部分,前部,数字和扩展名:

>>> 'FOLD/AAA.RST.12345.TXT'.rsplit('.', 2)
['FOLD/AAA.RST', '12345', 'TXT']

我们将它们分配给frontnumbersext

然后我们再次使用str.join

构建一个字符串
>>> '.'.join(['FOLD/AAA.RST', 'TXT']
'FOLD/AAA.RST.TXT'

这就是get_template返回的内容:

>>> get_template('FOLD/AAA.RST.12345.TXT')
'FOLD/AAA.RST.TXT'

我们可以这样使用它:

mylist = [
    "FOLD/AAA.RST.12345.TXT",
    "FOLD/BBB.RST.12345.TXT",
    "RUNS/AAA.FGT.12345.TXT",
    "FOLD/AAA.RST.87589.TXT",
    "RUNS/AAA.RST.11111.TXT"
]

from pprint import pprint

pprint(filter(keep, mylist))

输出:

['FOLD/AAA.RST.12345.TXT'
 'FOLD/AAA.RST.87589.TXT']

答案 2 :(得分:0)

您可以使用正则表达式定义模式,并检查您的字符串是否与该模式匹配。

在这种情况下,请分割target并在\d+xxx/yyy.zzz.部分之间插入.txt。使用它作为模式。

模式\d+表示任意数量的数字。模式的其余部分将根据xxx/yyy.zzz.txt的文字值创建。由于句点在正则表达式中具有特殊含义,因此我们必须使用\将其转义。

import re

selected_list = []
for target in target_list:
    base, ext = target.rsplit(".", 1)
    pat = ".".join([base, "\d+", ext] ).replace(".", "\.")
    selected_list.append([s for s in mylist if re.match(pat, s) is not None])
print(selected_list)
#[['FOLD/AAA.RST.12345.TXT', 'FOLD/AAA.RST.87589.TXT']]

如果模式不匹配,则re.match返回None

答案 3 :(得分:0)

为什么不使用filter + lambda函数:

import re
result=list(filter(lambda item: re.sub(r'.[0-9]+', '', item) == target_list[0], mylist))

一些评论:

  • 方法是从比较中排除数字。所以在 lambda函数,对于每个mylist项目,我们将数字替换为”, 然后与target_list中的唯一项目target_list [0]比较。
  • filter将匹配lambda函数为True的所有项目
  • 包装list中的所有内容,以将filter对象转换为list 对象