Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply n-times a function with map

I am starting to learn how to use python in a functional way and I am facing a problem I can't solve.

I have the following code (take in part from this question) which does exactly what I want:

url = "www.testpage.com/"
def gen_url(prefix, suffix, places=3):
    pattern = "{}{{:0{}d}}{}".format(prefix, places, suffix)
    for i in count(1):
        yield pattern.format(i)

list_of_urls = []
for c in "xyz":
    g = gen_url(url+c,"&show=more")
    for x in range(2):
        list_of_urls.append(next(g))

And it generates something like this:

www.testpage.com/x001&show=more
www.testpage.com/y001&show=more
www.testpage.com/z001&show=more
www.testpage.com/x002&show=more
www.testpage.com/y002&show=more
www.testpage.com/z002&show=more

As you can see, It stops at 002 because of:

    ...
    for x in range(2):
        list_of_urls.append(next(g))
    ...

All the time I start with an empy list, use a for loop and fill it. I am trying to use map in this way and get rid of the for loop:

urls = map(lambda x:next(gen_url(url+x,"&show=more")),"xyz")

And it works. But I can only get to 001. Let's assume I want to reach 002; I am trying something like the following, but It doesn't work:

urls = imap((lambda x:next(gen_url(url+x,"&show=more")),"xyz"),2)

And this as well doesn't work:

urls = map((lambda x:next(gen_url(url+x,"&show=more")),"xyz"),repeat(2))

Could somebody explain me how to properly use the iterators in this case?

like image 557
Angelo Avatar asked Aug 31 '25 15:08

Angelo


2 Answers

Functionally it would look like this:

def gen_url(prefix, suffix, id, places=3):
    pattern = "{}{{:0{}d}}{}".format(prefix, places, suffix)
    return pattern.format(id)

url = "www.testpage.com/"
a = [ gen_url(url + l, "&show=more", n) for l in "xyz" for n in range(1,4) ]
print a

So now your gen_url is a pure function that accepts everything from outside.

And your're generating a cartesian product (basically all permutations) of 2 sequences "xyz" and [1, 2, 3]

The script above generates:

['www.testpage.com/x001&show=more',
 'www.testpage.com/x002&show=more',
 'www.testpage.com/x003&show=more', 
 'www.testpage.com/y001&show=more', 
 'www.testpage.com/y002&show=more', 
 'www.testpage.com/y003&show=more', 
 'www.testpage.com/z001&show=more',
 'www.testpage.com/z002&show=more',
 'www.testpage.com/z003&show=more']
like image 68
zerkms Avatar answered Sep 02 '25 16:09

zerkms


Prefix and suffix are detracting from the simple logic in gen_url. They can be pulled out.

Try this:

from itertools import count, islice

def gen_url(places=3):
    for i in count(1):
        yield "{{:0{}d}}".format(places).format(i)

url = "www.testpage.com/"
list_of_urls = [url+c+x+"&show=more" for c in "xyz" for x in islice(gen_url(), 0, 2)]
like image 39
sureshvv Avatar answered Sep 02 '25 16:09

sureshvv