繁体   English   中英

将 for 循环转换为 List Comprehension Python

[英]Convert for loop to List Comprehension Python

问题是对于所有数字 (1 - 20),任何数字中最高的一位数 (1 - 9) 都可以被整除。

我有一个 for 循环,如下所示:

values = [[] for value in range(1, 11)]

for num in range(1, 21):
    highest = 0
    for div in range(1, 10):
        if(num % div == 0 and div > highest):
            highest = div
    
    values[highest].append(num)

以下 for 循环输出:

[[], [1, 11, 13, 17, 19], [2], [3], [4], [5, 10, 15, 20], [6, 12], [7, 14], [8, 16], [9, 18]]

输出中的空列表 [] 可以忽略。 例如:

[[1, 11, 13, 17, 19], [2], [3], [4], [5, 10, 15, 20], [6, 12], [7, 14], [8, 16], [9, 18]]

我想将以下 for 循环转换为列表理解,任何人都可以帮助我。

问题是对于所有数字 (1 - 20),任何数字中最高的一位数 (1 - 9) 都可以被整除。

我会使用list.pop()以另一种方式实现它:

nums = list(range(1, 21))
values = []
for d in range(9, 0, -1):
    temp = []
    for i in range(len(nums) - 1, -1, -1):  # iterating in reverse order
        if not nums[i] % d:  # nums[i] % d == 0
            temp.insert(0, nums.pop(i))
    values.insert(0, temp)
print(values)

基本上,我们初始化从120的数字列表和可被数字整除的弹出值。 我在这里使用了list.insert()使其以与您的解决方案相同的顺序产生结果。

评论中,我发布了将以相反顺序生成列表的代码,如下所示:

nums = list(range(1, 21))
values = [[nums.pop(i) for i in range(len(nums) - 1, -1, -1) if not nums[i] % d] for d in range(9, 0, -1)]

您可以添加两个reversed()调用(正如我在另一条评论中建议的那样)或使用切片反转它以使其以正确的顺序返回列表:

nums = list(range(1, 21))
values = [[nums.pop(i) for i in range(len(nums) - 1, -1, -1) if not nums[i] % d][::-1] for d in range(9, 0, -1)][::-1]

更新。 我决定添加一些测试结果,这应该有助于了解为什么列表理解不会让它变得更好。 如果你想重现测试,代码在这里

测试结果(越低越好)

Temple Version: 0.49361748499999997
Tranbi: 1.794325605
JonSG: 5.4978652320000005
JonSG(+ Olvin): 4.834248347000001
Olvin Roght (v1): 0.34827960000000147
Olvin Roght (v2): 0.4133600079999997
Kelly Bundy: 0.19429717999999951
Temple Version(+ Kelly): 0.20479166999999876

这是对理解略有不同的看法。

values = [
    [
        num for num
        in range(1, 21)
        if index == max([
            i for i
            in range(1, 10)
            if not num%i
        ])
    ] for index, _
    in enumerate(range(1, 11))
]
print(values)

这会给你:

[[], [1, 11, 13, 17, 19], [2], [3], [4], [5, 10, 15, 20], [6, 12], [7, 14], [8, 16], [9, 18]]

它可以简化一点,但我试图尽可能地匹配你所做的。

这是@olvin-roght 强调的一个简单的简化和改进:

values = [
    [
        num for num in range(1, 21)
        if index == next(i for i in range(9, 0, -1) if not num%i)
    ] for index in range(10)
]

为什么需要第一个空列表? @Olvin 提出的解决方案巧妙地利用了pop 你必须扭转它才能得到你想要的东西。

这是一个可能更容易理解并为您提供预期结果的解决方案:

print([ [num for num in range(1,21) if num % div == 0 and all(num % x != 0 for x in range(div + 1, 10)) ] for div in range(1,10)])

输出:

[[1, 11, 13, 17, 19], [2], [3], [4], [5, 10, 15, 20], [6, 12], [7, 14], [8, 16], [9, 18]]

使用all将产生更多的计算时间(因此在其他解决方案中会相反)。
如果你想训练,创造理解很有趣,但循环也很好。 在这里更容易阅读!

编辑

由于有这么多人对这个问题和我的回答发表评论,我开始仔细研究问题并为所有解决方案计时。 事实证明@Olvin 的解决方案是最快的,并且与 OP 的循环速度相匹配。 其次是我的解决方案(在我的机器上慢了大约 3 倍)和@JonSG 的解决方案(慢了 9 倍)结果反转列表比我想象的要优化得多......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM