首页 > 解决方案 > Python:使用map做while循环等效

问题描述

有没有办法在不使用循环/递归/理解的情况下仅在满足条件时继续调用函数?我只能使用地图和过滤器。

我正在对列表进行冒泡排序,我需要重申,直到有一个完整的通过而没有任何交换。我为此使用了一个计数器。

这是我到目前为止所拥有的:

def sort(l, i, cnt):
    if i < len(l) - 1 and l[i] > l[i+1]:
        l[i], l[i+1] = l[i+1], l[i]
        cnt += 1
  
    return l[i]
    

def main(l):
    cnt = 0
    l = list(map(lambda i: sort(l, i, cnt), range(len(l))))

我不确定如何仅在 cnt != 0 时继续调用 sort 。感谢任何帮助。

标签: pythonsorting

解决方案


这是不常见的要求,但如果允许您使用其他函数来实际执行迭代器,这是可能的。因为 bothmapfilterboth 都只返回迭代器,所以你必须使用sum, list, 或tuple例如实际使迭代器返回它们的值。

在这里,我将使用一个函数来比较列表中的 2 个连续元素,在它们按升序排列时返回 0,然后交换它们,如果不是,则返回 1。在此函数上使用sumon amap将返回一次通过的交换次数:

def sort2(l, i):
    if (l[i] > l[i+1]):
        l[i], l[i+1] = l[i+1], l[i]
        return 1
    return 0

您可以使用以下命令执行通行证

sum(map(lambda i: sort2(l, i), range(len(l) -1)))

并且您通过对所有通道使用第二个映射来执行完整的冒泡排序:

sum(map(lambda j: sum(map(lambda i: sort2(l, i), range(len(l) -j))), range(1, len(l))))

为了在一次传递导致 0 交换时立即停止,我会使用一个提高 a 的函数进行过滤StopIteration,当它得到 0 时,因为如果我们使用 sum,一旦列表排序,传递就会返回 0,并且 StopIteration 将轻轻地停止迭代器:

def stop(x):
    # print(x)   # uncomment to control the actual calls
    if x == 0:
        raise StopIteration
    return True

让我们结合一切:

tuple(filter(stop, map(lambda j: sum(map(lambda i: sort2(l, i), range(len(l) -j))
               ), range(1, len(l)))))

演示:

随着l = [1, 3, 5, 2, 4],这给出(在 中未print注释stop):

2
1
0
(2, 1)

所以我们正确地得到了:

  • 第一次通过导致 2 次交换 ((5,2) 和 (5,4))
  • 第二遍导致 1 次交换 ((3,2))
  • 第三遍导致 0 交换,stop过滤器实际上停止了迭代器。

话虽这么说,这是一个很好的练习,但我永远不会在现实世界的程序中这样做......


推荐阅读