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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何根据多个条件过滤列表?相关的知识,希望对你有一定的参考价值。

我有以下列表:

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

如果xxxyyyzzztarget_list一致,则应选择记录。否则应将其从结果中删除。

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

selected_list = []
for t in target_list:
   r1 = l.split("/")[0]
   a1 = l.split("/")[1].split(".")[0]
   b1 = l.split("/")[1].split(".")[1]

   for l in mylist:
      r2 = l.split("/")[0]
      a2 = l.split("/")[1].split(".")[0]
      b2 = l.split("/")[1].split(".")[1]

      if (r1==r2) & (a1==a2) & (b1==b2):
         selected_list.append(l)
答案

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

  • 通过在集合中缓存有关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']
另一答案

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

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反向搜索字符串并将其分割为给定字符,在这种情况下为str.rsplit。参数.表示最多只能执行两个分割。这给了我们三个部分,前部,数字和扩展名:

2

我们将它们分配给>>> 'FOLD/AAA.RST.12345.TXT'.rsplit('.', 2) ['FOLD/AAA.RST', '12345', 'TXT'] frontnumbers

然后我们再次使用ext建立一个字符串

str.join

所以这是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'] 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功能:

filter

一些评论:

  • 方法是从比较中排除数字。所以在lambda功能,对于每个mylist项目,我们将数字替换为”,然后与target_list中的唯一项目target_list [0]比较。
  • [import re result=list(filter(lambda item: re.sub(r'.[0-9]+', '', item) == target_list[0], mylist)) 将匹配lambda函数为lambda的所有项目
  • filter中的所有内容包装起来,从True对象转换为list对象

以上是关于如何根据多个条件过滤列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何过滤复杂对象的列表,以便如果两个具有字段值,我会根据条件删除一个

Access 2010:根据特定组合框条件过滤字段中包含多个值的报表

多个条件的过滤列表

基于Python中的多个条件进行过滤

如何过滤具有多个条件的托管对象实体

React:使用多个复选框过滤数组列表