Welcome, guest | Sign In | My Account | Store | Cart

Do nested for loops on an arbitrary list of iterable things.

Python, 65 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class nloop:
    def __init__(self,*list):
        self.list = list
        self.memo_array = [None] * len(list)
        self.iter_list = []
        exec(self.n_combo(list))
    def __getitem__(self,index):
        return self.iter_list[index]

    def n_combo(self,lists):
        zipped = zip(list(range(len(lists))), lists)
        zipdex = map((lambda x: x[0]), zipped)
        str = "for"
        cmma = ''
        fora = ''
        for z in zipdex:
            cmma = cmma + ', ' + 'i%s' % z
        cmma = cmma[1:]
        i = 0
        for z in zipdex:
            fora = fora + 'for ' + 'i%s' % z + ' in self.list[%s] ' % i
            i = i + 1
        str = str + cmma + ' in [(' + cmma + ') ' + fora + ']:'

        cmd = "self.iter_list.append((" + cmma + "))"
        return str  + cmd


if __name__ == '__main__':
    for tup in nloop(list("abcdef"),
                     list(range(1,50)),
                     list("hijklmno"),
                     list(range(1,7))):
        print tup

###########################################

class nloop:
    def __init__(self,*varg):
        self.list = list(varg)
        self.iter_list = []

        self.memo = [None] * len(self.list)
        if len(self.list):
            self.n_iter(0, self.list)

    def __getitem__(self,index):
        return self.iter_list[index]

    def n_iter(self,index,stack):
        x = stack[index]
        for i in x:
            self.memo[index] = i
            if index == len(stack) - 1:
                self.iter_list.append(tuple(self.memo))
            else:
                self.n_iter(index + 1, stack)
                

if __name__ == '__main__':
    for tup in nloop(list("abcdef"),
                     list(range(1,50)),
                     list("hijklmno"),
                     list(range(1,7))):
        print tup

The first version might be faster.

2 comments

Simon Watts 20 years, 1 month ago  # | flag

how "for X in S" terminates. This article was indirectly useful, in highlighting that you done need to know the __len__ of the collection object S in "for X in S" loops. Just providing __getitem__(self,index) is sufficient, and throwing IndexError when it goes out of bounds.

The reason this is useful to me, is where S is an extension object which interfaces to some other date element source, where we can get the next element, but dont know where the end is until we reach it.

pascal barbedor 17 years, 7 months ago  # | flag

a shorter version.

def nloop(*lol):
    l=len(lol)
    dims=map(len,lol)
    totl=reduce(lambda x,y:x*y,dims)
    i=0
    idx=[0]*l
    while totl>i:
        a=i
        i+=1
        for j in range(l-1,-1,-1):
            a,b= divmod(a,dims[j])
            idx[j]=lol[j][b]
        yield tuple(idx)


amounts to transforming a n-dimensional array in a long vector, and
convert the linear index to multiple index.
Created by philip nunez on Thu, 1 Nov 2001 (PSF)
Python recipes (4591)
philip nunez's recipes (6)

Required Modules

  • (none specified)

Other Information and Tasks