how to iterate/zip elements of multiple list with random index as start position
Question:
I have multiple lists of equal length as follows:
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
listpack = [list1, list2, list3, list4]
#random select one element per list
rand = more_itertools.random_product(*listpack)
#locate their index
for ii in rand: #strings
for xx in listpack: #list of lists
pass
index = xx.index(ii[:])
Problem area:
How to cycle round all the list using the above index as start position
for example:
if the rand result above is ("d, h, q, v")
next will be ("e, i, r, w"), ("f, j, m, x"), ("a, k, n, s")
till the cycle reach their starting position again)
I have tried to zip but it always start from the beginning of the list
cyclist = list(map(''.join, zip(*listpack)))
I have also checked all thread suggested by stacks but not related to this.
Any faster approach to the entire code is also welcome 🙂
Thanks
Answers:
From lists
You can use this:
import more_itertools as mi
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
listpack = [list1, list2, list3, list4]
rand = mi.random_product(*listpack)
indexes = [l.index(r) for l, r in zip(listpack, rand)]
for i in range(len(list1)):
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
print(listpack[j][k], end='')
print('')
Output:
Run 1
birt
cjmu
dknv
elow
fgpx
ahqs
Run 2
cjov
dkpw
elqx
fgrs
ahmt
binu
From files
For files, use:
import more_itertools as mi
filenames = ['list1.txt', 'list2.txt', 'list3.txt', 'list4.txt']
listpack = []
for filename in filenames:
with open(filename) as f:
listpack.append(f.read().splitlines())
rand = mi.random_product(*listpack)
indexes = [l.index(r) for l, r in zip(listpack, rand)]
for i in range(len(listpack[0])):
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
print(listpack[j][k], end='')
print('')
list1.txt:
a
b
c
d
e
f
Output:
djru
ekmv
flnw
agox
bhps
ciqt
Only one print / output stored in variable
If you want only one print
the use the following instead of the loop:
output = []
for i in range(len(listpack[0])):
output.append('')
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
output[-1] += listpack[j][k]
print(output)
Output:
['dgrv', 'ehmw', 'finx', 'ajos', 'bkpt', 'clqu']
One approach using the standard library:
import random
# for reproducibility
random.seed(43)
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
# generate random starting points for each list
s1 = random.randrange(0, len(list1))
s2 = random.randrange(0, len(list2))
s3 = random.randrange(0, len(list3))
s4 = random.randrange(0, len(list4))
for tup in zip(list1[s1:] + list1[:s1], list2[s1:] + list2[:s1], list3[s1:] + list3[:s1], list4[s1:] + list4[:s1]):
print(tup)
Output
('a', 'g', 'm', 's')
('b', 'h', 'n', 't')
('c', 'i', 'o', 'u')
('d', 'j', 'p', 'v')
('e', 'k', 'q', 'w')
('f', 'l', 'r', 'x')
The function random.randrange
will generate a random index. Then you could use the expression:
list1[s1:] + list1[:s1]
To generate a cycle of the original list, for example for list1
and s1 = 2
, the above expression returns:
['c', 'd', 'e', 'f', 'a', 'b']
I have multiple lists of equal length as follows:
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
listpack = [list1, list2, list3, list4]
#random select one element per list
rand = more_itertools.random_product(*listpack)
#locate their index
for ii in rand: #strings
for xx in listpack: #list of lists
pass
index = xx.index(ii[:])
Problem area:
How to cycle round all the list using the above index as start position
for example:
if the rand result above is ("d, h, q, v")
next will be ("e, i, r, w"), ("f, j, m, x"), ("a, k, n, s")
till the cycle reach their starting position again)
I have tried to zip but it always start from the beginning of the list
cyclist = list(map(''.join, zip(*listpack)))
I have also checked all thread suggested by stacks but not related to this.
Any faster approach to the entire code is also welcome 🙂
Thanks
From lists
You can use this:
import more_itertools as mi
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
listpack = [list1, list2, list3, list4]
rand = mi.random_product(*listpack)
indexes = [l.index(r) for l, r in zip(listpack, rand)]
for i in range(len(list1)):
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
print(listpack[j][k], end='')
print('')
Output:
Run 1
birt
cjmu
dknv
elow
fgpx
ahqs
Run 2
cjov
dkpw
elqx
fgrs
ahmt
binu
From files
For files, use:
import more_itertools as mi
filenames = ['list1.txt', 'list2.txt', 'list3.txt', 'list4.txt']
listpack = []
for filename in filenames:
with open(filename) as f:
listpack.append(f.read().splitlines())
rand = mi.random_product(*listpack)
indexes = [l.index(r) for l, r in zip(listpack, rand)]
for i in range(len(listpack[0])):
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
print(listpack[j][k], end='')
print('')
list1.txt:
a
b
c
d
e
f
Output:
djru
ekmv
flnw
agox
bhps
ciqt
Only one print / output stored in variable
If you want only one print
the use the following instead of the loop:
output = []
for i in range(len(listpack[0])):
output.append('')
for j in range(len(listpack)):
k = (indexes[j] + i) % len(listpack[j])
output[-1] += listpack[j][k]
print(output)
Output:
['dgrv', 'ehmw', 'finx', 'ajos', 'bkpt', 'clqu']
One approach using the standard library:
import random
# for reproducibility
random.seed(43)
list1 = ["a", "b", "c", "d", "e", "f"]
list2 = ["g", "h", "i", "j", "k", "l"]
list3 = ["m", "n", "o", "p", "q", "r"]
list4 = ["s", "t", "u", "v", "w", "x"]
# generate random starting points for each list
s1 = random.randrange(0, len(list1))
s2 = random.randrange(0, len(list2))
s3 = random.randrange(0, len(list3))
s4 = random.randrange(0, len(list4))
for tup in zip(list1[s1:] + list1[:s1], list2[s1:] + list2[:s1], list3[s1:] + list3[:s1], list4[s1:] + list4[:s1]):
print(tup)
Output
('a', 'g', 'm', 's')
('b', 'h', 'n', 't')
('c', 'i', 'o', 'u')
('d', 'j', 'p', 'v')
('e', 'k', 'q', 'w')
('f', 'l', 'r', 'x')
The function random.randrange
will generate a random index. Then you could use the expression:
list1[s1:] + list1[:s1]
To generate a cycle of the original list, for example for list1
and s1 = 2
, the above expression returns:
['c', 'd', 'e', 'f', 'a', 'b']