如何根据多个条件过滤列表?
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
如果xxx
,yyy
和zzz
与target_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']
,front
和numbers
。
然后我们再次使用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
对象
以上是关于如何根据多个条件过滤列表?的主要内容,如果未能解决你的问题,请参考以下文章
如何过滤复杂对象的列表,以便如果两个具有字段值,我会根据条件删除一个