使用 Map 和 Filter 的列表理解的等价物

Equivalent of List Comprehension Using Map and Filter

我想使用映射 and/or 过滤函数来编写此代码。它 returns 列表中项目的索引提供了目标的总和

我为此使用了列表理解,但看不到如何将第二个 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]

双循环可以编码为 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 returns 一个包含 num 中元素的元组迭代器,(x, y) 类似于您使用的嵌套循环。 在我们筛选那些元组中哪些总和等于 tgt 时,使用 sum 是更好的选择,但请注意它与 x[0] + x[1] 相同(记住我们给出的元组像 (2, 2) 到那个函数)。

过滤后,我们将应用保留函数 num.index 的每个元组,因为我们有元组,我们只需要使用其中一个值,记住第一个匹配嵌套的 for 循环x 因此 num.index(x[0])

由于 filtermap 都处理序列中的单个项目,因此您必须从列表中每个项目的角度而不是项目组合的角度来查看您的逻辑,这意味着您需要将列表理解中使用的表达式改写为单个项目的函数。因此,代替过滤条件 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)))

这个returns:

[0, 1, 2, 4, 6, 7]

试试这个!您可以使用 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)) 的自乘积。

使用 mapfilter:

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 的长度减一之间的数字对,对于这些数字 num 在那些相应索引处的值等于目标。由于乘积 returns 一对索引,而您只对第一个值感兴趣,因此 map filteritemgetter(0) 的结果得到第一个元素。

更紧凑的列表理解:

[i for i, j in product(range(len(num)), range(len(num))) if num[i] + num[j] == tgt]