将 for 循环转换为列表理解 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 循环转换为列表推导式,谁能帮帮我。
为什么需要第一个空列表? @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 倍)结果证明反转列表比我想象的优化得更好......
这里的理解略有不同。
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)
]
问题是对于所有数字 (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)
基本上,我们初始化从 1
到 20
的数字列表和可被数字整除的弹出值。我在这里使用了 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()
(as i suggested in ) 调用或使用切片反转它以使其 return 以正确的顺序列出:
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]
Upd. 我决定添加一些测试结果,这应该有助于了解为什么列表理解没有使它变得更好。如果你想重现测试,代码是 here.
测试结果 (越低越好):
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
问题是对于所有数字 (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 循环转换为列表推导式,谁能帮帮我。
为什么需要第一个空列表? @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 的
这里的理解略有不同。
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)
]
问题是对于所有数字 (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)
基本上,我们初始化从 1
到 20
的数字列表和可被数字整除的弹出值。我在这里使用了 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()
(as i suggested in
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]
Upd. 我决定添加一些测试结果,这应该有助于了解为什么列表理解没有使它变得更好。如果你想重现测试,代码是 here.
测试结果 (越低越好):
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