我已经使用列表推导式来实现这个功能,但不知道如何将第二个for循环嵌入到map/filter函数中。 如果我为map/filter函数的函数参数定义自己的函数,我不确定要使用哪种语法。
num = [2,5,7,11,6,15,3,4]
tgt= 9
[num.index(x) for x in num for y in num if x + y == tgt]
结果:
[0, 1, 2, 4, 6, 7]
num = [2,5,7,11,6,15,3,4]
tgt= 9
[num.index(x) for x in num for y in num if x + y == tgt]
结果:
[0, 1, 2, 4, 6, 7]
由于filter
和map
都作用于序列中的单个项目,因此您必须从列表中每个项目的角度来查看逻辑,而不是项目组合的角度。这意味着您需要将列表推导中使用的表达式重新构造为每个单独项目的函数。因此,过滤条件x + y == tgt
可以视为x == tgt - y
,其中y
还必须是num
列表中的项目之一,以便您的列表推导可以重写为:
[num.index(x) for x in num if x in {tgt - y for y in num}]
num
中的每个项目映射到其与tgt
之间的差异来创建一个集合,这可以使用tgt.__sub__
方法完成,然后测试num
中的每个项目x
是否是该集合的成员,这可以使用集合的__contains__
方法完成,最后将过滤后的序列映射到num.index
以输出每个匹配项的索引:list(map(num.index, filter(set(map(tgt.__sub__, num)).__contains__, num)))
[0, 1, 2, 4, 6, 7]
itertools.product
函数编写:>>> list(map(lambda x: num.index(x[0]), filter(lambda x: sum(x) == tgt, itertools.product(num, num))))
[0, 1, 2, 4, 6, 7]
让我们来剖析代码:
filter(lambda x: sum(x) == tgt, itertools.product(num, num))
itertools.product
返回一个元组迭代器,其中的元素在 num 中,类似于您使用的嵌套循环中的 (x, y)
。
然后我们过滤那些元组求和等于 tgt
的元素,使用 sum
是更好的选择,但请注意它与 x[0] + x[1]
相同(记住我们将像 (2, 2)
这样的元组传递给该函数)。
一旦我们过滤出剩下的元组,我们对每个元组应用函数 num.index
,因为我们有元组,所以我们只需要使用其中一个值,记住第一个值匹配嵌套循环中的 x
,因此是 num.index(x[0])
试试这个!你可以使用 itertools.product
来获取每个组合。然后过滤组合列表,找到其总和为 tgt
的项。接着对这些结果映射一个 lambda 函数,以获取这些组合中第一项的索引。
list(map(lambda x: num.index(x[0]), (filter(lambda x: sum(x) == tgt, itertools.product(num, repeat=2)))))
反复调用num.index
非常低效。每次找到满足条件的数字时,对index
的调用都需要对列表进行顺序扫描。
相反,将循环转换为列表中的索引。通过索引数组进行比较(随机访问),这将更加高效。
正如其他人指出的那样,您可以使用itertools.product
,但是不是num
与自身的乘积,而是range(len(num))
的自我乘积。
使用map
和filter
:
from operator import itemgetter
from itertools import product
res = map(
itemgetter(0),
filter(
lambda c: num[c[0]]+num[c[1]] == tgt,
product(range(len(num)),range(len(num)))
)
)
print(list(res))
#[0, 1, 2, 4, 6, 7]
内部的filter
正在过滤0到num
长度减1之间的所有数字对,其中在相应索引处的num
的值等于目标。由于product返回一对索引,您只对第一个值感兴趣,因此使用itemgetter(0)
将filter
的结果与map
映射以获取第一个元素。
更紧凑的写法是列表推导式:
[i for i, j in product(range(len(num)), range(len(num))) if num[i] + num[j] == tgt]
set
替代list(map(tgt.__sub__, num))
可以获得更好的查找效果。 - Netwave