python - Python - 嵌套在地图内的过滤器会产生意外的输出
问题描述
我有一个文件名(字符串)列表和一组由浮点数组成的 ls 。最初,我想根据预先确定的表达式过滤与 ls 的每个元素匹配的所有文件:我将所有实际上是整数的浮点数转换为整数并将其输入.format
以创建适当的搜索字符串 ( exprs
)。这会产生预期的字符串序列。我现在想使用 re.search 过滤“文件”,但据我了解,我需要为 exprs 的每个输出使用不同的过滤器。所以我把它嵌套在一个 map 函数中:
t = 'Matrix'
exprs = map('{}_spike_{}_D1_1'.format , cycle([t]) ,(int(x) if x.is_integer() else x for x in ls))
y = map(lambda f:filter(lambda i : re.search(f,i), files), exprs)
Print(next(exprs))
产生预期的输出,即'Matrix_spike_50_D1_1'
。如果我“冻结” re.search 中的表达式,即通过做b = next(exprs)
,re.search(b, [...])
我得到预期的输出(即文件名,正确选择)。但是当我尝试使用map
消耗所有输出exprs
并返回结果时filter([...])
,我得到了
- 过滤器对象而不是地图对象
- 两个相同的过滤器对象,当通过 a 彻底运行它时
while True
,捕获所有StopIterations
并恢复
如何修改它以返回过滤每个 exprs 的返回文件?
解决方案
如果我正确理解了您的问题,您将获得一个文件列表,例如:
files = ['a', 'b', 'Matrix_spike_2_D1_1', 'c', 'Matrix_spike_4_D1_1']
和一个浮点数列表,应该是整数(但可能不是全部都是):
ls = [1.1, 2.0, 3.0, 4.0, 5.0]
从ls
整数列表中,构造名称“Matrix_spike_2_D1_1”、“Matrix_spike_3_D1_1”等,然后从files
列表中选择满足rex.search
调用的文件。当然,search
不使用^
和$
锚的方法不会完全匹配,所以我想知道你是否真的打算使用该fullmatch
方法。
首先,你有:
t = 'Matrix'
exprs = map('{}_spike_{}_D1_1'.format , cycle([t]) ,(int(x) if x.is_integer() else x for x in ls))
我相信这被简化为:
exprs = map('Matrix_spike_{}_D1_1'.format, (int(x) for x in ls if x.is_integer())
请注意,我仅从ls
中选择整数值,我相信这是您的意图。为了采用您的方法,我相信最简单的补救措施是定义一个函数filter_func
:
import re
ls = [1.1, 2.0, 3.0, 4.0, 5.0]
files = ['a', 'b', 'Matrix_spike_2_D1_1', 'c', 'Matrix_spike_4_D1_1']
exprs = list(map(re.compile, map('Matrix_spike_{}_D1_1'.format, (int(x) for x in ls if x.is_integer()))))
def filter_func(f):
for expr in exprs:
if expr.search(f):
return True
return False
matched_files = list(filter(filter_func, files))
print(matched_files)
印刷:
['Matrix_spike_2_D1_1', 'Matrix_spike_4_D1_1']
或者使用更“实用”但效率可能较低的方法:
import re
import operator
import functools
ls = [1.1, 2.0, 3.0, 4.0, 5.0]
files = ['a', 'b', 'Matrix_spike_2_D1_1', 'c', 'Matrix_spike_4_D1_1']
exprs = list(map(re.compile, map('Matrix_spike_{}_D1_1'.format, (int(x) for x in ls if x.is_integer()))))
filter_func = lambda f: functools.reduce(operator.or_, map(lambda expr: bool(expr.search(f)), exprs), False)
matched_files = list(filter(filter_func, files))
print(matched_files)
印刷:
['Matrix_spike_2_D1_1', 'Matrix_spike_4_D1_1']
但我相信你的方法不是最有效的。您应该对files
列表的每个元素进行一次正则表达式搜索。在上面的示例中,该正则表达式将是:
rex = re.compile('Matrix_spike_(?:2|3|4|5)_D1_1')
在上面的正则表达式中,您会将files
列表中的每个元素与您正在查找的所有 4 个可能的文件名进行匹配。这将代码简化为:
import re
ls = [1.1, 2.0, 3.0, 4.0, 5.0]
files = ['a', 'b', 'Matrix_spike_2_D1_1', 'c', 'Matrix_spike_4_D1_1']
sub_rex = '|'.join(str(int(x)) for x in ls if x.is_integer())
rex = re.compile('Matrix_spike_(?:' + sub_rex + ')_D1_1');
matched_files = list(filter(rex.search, files))
print(matched_files)
印刷:
['Matrix_spike_2_D1_1', 'Matrix_spike_4_D1_1']
如果您打算对文件名进行完全匹配(相等),那么以下代码将是最有效的,因为它将您要查找的名称添加到集合中,并且每次比较都将是一个常数时间查找:
ls = [1.1, 2.0, 3.0, 4.0, 5.0]
files = ['a', 'b', 'Matrix_spike_2_D1_1', 'c', 'Matrix_spike_4_D1_1']
sought_files = {f'Matrix_spike_{int(x)}_D1_1' for x in ls if x.is_integer()}
matched_files = list(filter(lambda f: f in sought_files, files))
print(matched_files)
推荐阅读
- jquery - 你如何根据用户的机器本地时间将 webflow 的主要 css 交换到其他 Github 托管 css?
- java - 从线程获取值并在线程解析后立即在主线程中使用它的最佳方法是什么?
- android - 如何通过 HTTP 请求将 Flutter 应用程序连接到 AWS EC2 实例
- android - 垂直对齐两个 TextView,使它们的宽度完全相同
- haproxy - LetsEncrypt 跨服务器的多个 HaProxy 实例
- swift - 如何创建一个函数来检查用户是否被阻止?
- function - 绘图分段函数
- reactjs - 如何在反应路由器dom的UseHistory中传递多个对象?
- excel - 如何在可编辑的工作表内显示对外部数据源的查找?
- mysql - 如何从最小索引到最大索引对 SQL 结果进行排序?