Transforming nested Python loops into list comprehensions
I've started working on some Project Euler problems, and have solved number 4 with a simple brute force solution:
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)]))])
After solving, I tried to make it as compact as possible, and came up with that horrible bottom line!
Not to leave something half-done, I am trying to condense the mprods
function into a list comprehension. So far, I've come up with these attempts:
[d*e for d,e in (range(a,b), range(a,b))]
Obviously completely on the wrong track. :-)[d*e for x in [e for e in range(1,5)] for d in range(1,5)]
This gives me[4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16, 4, 8, 12, 16]
, where I expect[1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]
开发者_如何学运维 or similar.
Any Pythonistas out there that can help? :)
c = range(a, b)
print [d * e for d in c for e in c]
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)
is likerange(900,1000)
but instead of returning a list it returns an object that generates the numbers in the range on demand. For looping, this is slightly faster than range() and more memory efficient.product(xrange(900,1000),xrange(900,1000))
gives the Cartesian product of the input iterables. It is equivalent to nested for-loops. For example,product(A, B)
returns the same as:((x,y) for x in A for y in B)
. The leftmost iterators are in the outermost for-loop, so the output tuples cycle in a manner similar to an odometer (with the rightmost element changing on every iteration).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]
is list slicing shorthand to reverse a list.Note how everything is wrapped in a generator expression, a high performance, memory efficient generalization of list comprehensions and generators.
Also note that the largest palindrome made from the product of two 2-digit numbers is made from the numbers 91 99, two numbers in the
range(90,100)
. Extrapolating to 3-digit numbers you can userange(900,1000)
.
I think you'll like this one-liner (formatted for readability):
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])
Or slightly changed:
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])
Wonder how many parens that would be in Lisp...
精彩评论