将嵌套的Python循环转换为列表推导式
我开始做一些Project Euler的问题,已经用简单的暴力解法解决了第4题。
def mprods(a,b):
c = range(a,b)
f = []
for d in c:
for e in c:
f.append(d*e)
return f
max([z for z in mprods(100,1000) if str(z)==(''.join([str(z)[-i] for i in range(1,len(str(z))+1)]))])
解决之后,我想把代码尽量简化,结果写出了那行可怕的代码!
为了不让事情半途而废,我正在尝试把mprods
这个函数压缩成一个列表推导式。到目前为止,我尝试了以下几种方法:
[d*e for d,e in (range(a,b), range(a,b))]
显然,这完全是错的方向。:-)[d*e for x in [e for e in range(1,5)] for d in range(1,5)]
这个结果是[4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16]
,而我期待的是[1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]
或者类似的结果。
有没有Python高手能帮帮我?:)
3 个回答
我觉得你会喜欢这个一行代码(为了更好阅读格式化过):
max(z for z in (d*e
for d in xrange(100, 1000)
for e in xrange(100, 1000))
if str(z) == str(z)[::-1])
或者稍微改动一下:
c = range(100, 1000)
max(z for z in (d*e for d in c for e in c) if str(z) == str(z)[::-1])
想知道在Lisp语言中会有多少个括号吗……
from itertools import product def palindrome(i): return str(i) == str(i)[::-1] x = xrange(900,1000) max(a*b for (a,b) in (product(x,x)) if palindrome(a*b))
xrange(900,1000)
就像range(900,1000)
,不过它不是返回一个列表,而是返回一个可以按需生成这些数字的对象。这样在循环的时候,它比range()
稍微快一点,而且更省内存。product(xrange(900,1000),xrange(900,1000))
会给出输入的可迭代对象的笛卡尔积。它的效果和嵌套的 for 循环是一样的。比如说,product(A, B)
的结果和((x,y) for x in A for y in B)
是一样的。最左边的迭代器在最外层的 for 循环中,所以输出的元组会像里程表一样循环(最右边的元素在每次迭代时变化)。product('ab', range(3))
的结果是('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)
。product((0,1), (0,1), (0,1))
的结果是(0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...
str(i)[::-1]
是一种简便的列表切片方法,用来反转一个列表。注意所有内容都被包裹在一个 生成器表达式 中,这是一种高效且省内存的列表推导和生成器的扩展。
还要注意,两个两位数相乘得到的最大回文数是由 91 和 99 这两个数字组成的,它们都在
range(90,100)
这个范围内。如果推导到三位数,你可以使用range(900,1000)
。
在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如,有人可能会在使用某个特定的功能时,发现它并没有按照预期工作。这种情况可能是因为设置不正确,或者是使用的版本不兼容。
解决这类问题的第一步通常是检查文档,看看是否有说明或者提示。文档就像是使用说明书,可以帮助我们理解如何正确使用这些工具。
另外,很多时候,社区的讨论也能提供帮助。像StackOverflow这样的平台,很多开发者会分享他们的经验和解决方案。通过搜索相关的问题,我们可能会找到别人遇到过类似的情况,并且他们是如何解决的。
总之,遇到问题时,不要慌张,先查文档,再看看社区的讨论,通常能找到解决办法。
c = range(a, b)
print [d * e for d in c for e in c]