Is there any way to loop the second list multiple times to properly riffle two lists in Python similar to the Mathematica function?
Question:
I’m trying to convert the Mathematica built-in function, "Riffle" into python. Right now, my main focus is getting it to riffle two lists properly (I will worry about adding values at certain indexes later). The Mathematica function is tricky, its results are very dependent on the lengths of the lists. So far, I have created something that works the same as Mathematica for every case, except when the difference in the length of the lists is greater than the length of the second list. Mathematica handles this by iterating over the second list over and over again, until the first list has been exhausted. This is the issue I am having, I can’t seem to write something that does this successfully.
The main issue is within the second case where len1>len2. Any help would be much appreciated.
Here is my code:
def riffle(vec1, vec2):
'''
This function combines two lists into one new list in which every other value
of the resulting list is a value from the first list, separated by a value
from the second list. If the first list is larger, the second list will loop
over itself more than once. If the lists are not the same size, the last value is
removed from the result list. If they are the same size, each value from each
list will be added.
Inputs:
vec1: The first vector (list). The length of this vector determines how
the riffling will occur. ie: riffle(vec1,vec2) != riffle(vec2, vec1) if
the vectors are not the same length.
vec2: the second vector (list) which will be riffled into vec1.
Output:
result: a list containing the riffled vectors.
Example:
vector1 = [1, 2, 3]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3]
vector1 = [1, 2, 3, 4]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3, 'c', 4, 'd']
vector1 = [1, 2, 3, 4, 5, 6]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3, 'c', 4, 'a', 5, 'b', 6]
'''
result = []
len1 = len(vec1)
len2 = len(vec2)
min_len = min(len1, len2)
n = len1 -len2
m = n - len2
if len1 == len2:
for i in range(min_len):
result.append(vec1[i])
result.append(vec2[i])
if len1 > len2:
for i in range(min_len):
if vec2[i] == vec2[-1]:
if n < len2:
for j in range(n+1):
result.append(vec1[i+j])
result.append(vec2[j])
else:
for j in range(n+1):
if j == vec2[-1]:
for k in range(n):
result.append(vec1[i+k])
result.append(vec2[k])
else:
result.append(vec1[i+j])
result.append(vec2[j])
else:
result.append(vec1[i])
result.append(vec2[i])
result.pop(-1)
if len2 > len1:
for i in range(min_len):
result.append(vec1[i])
result.append(vec2[i])
result.pop(-1)
return result
My main struggle is within the case where n is not less than len2. I don’t know how to make python iterate over the second list more than once until the first list is exhausted. However, if someone knows a better method that accomplishes the same thing as Mathematica’s Riffle function in Python, please let me know.
Answers:
Use itertools.cycle()
to keep repeating vec2
as needed. Then use zip()
to loop over the two lists in parallel.
from itertools import cycle
def riffle(vec1, vec2):
if len(vec2) == 0: # special case for empty second vector
return vec1[:1]
result = []
for x, y in zip(vec1, cycle(vec2)):
result.append(x)
result.append(y)
if len(vec2) != len(vec1):
result.pop() # remove last element
return result
I’m trying to convert the Mathematica built-in function, "Riffle" into python. Right now, my main focus is getting it to riffle two lists properly (I will worry about adding values at certain indexes later). The Mathematica function is tricky, its results are very dependent on the lengths of the lists. So far, I have created something that works the same as Mathematica for every case, except when the difference in the length of the lists is greater than the length of the second list. Mathematica handles this by iterating over the second list over and over again, until the first list has been exhausted. This is the issue I am having, I can’t seem to write something that does this successfully.
The main issue is within the second case where len1>len2. Any help would be much appreciated.
Here is my code:
def riffle(vec1, vec2):
'''
This function combines two lists into one new list in which every other value
of the resulting list is a value from the first list, separated by a value
from the second list. If the first list is larger, the second list will loop
over itself more than once. If the lists are not the same size, the last value is
removed from the result list. If they are the same size, each value from each
list will be added.
Inputs:
vec1: The first vector (list). The length of this vector determines how
the riffling will occur. ie: riffle(vec1,vec2) != riffle(vec2, vec1) if
the vectors are not the same length.
vec2: the second vector (list) which will be riffled into vec1.
Output:
result: a list containing the riffled vectors.
Example:
vector1 = [1, 2, 3]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3]
vector1 = [1, 2, 3, 4]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3, 'c', 4, 'd']
vector1 = [1, 2, 3, 4, 5, 6]
vector2 = ['a', 'b', 'c', 'd']
result = [1, 'a', 2, 'b', 3, 'c', 4, 'a', 5, 'b', 6]
'''
result = []
len1 = len(vec1)
len2 = len(vec2)
min_len = min(len1, len2)
n = len1 -len2
m = n - len2
if len1 == len2:
for i in range(min_len):
result.append(vec1[i])
result.append(vec2[i])
if len1 > len2:
for i in range(min_len):
if vec2[i] == vec2[-1]:
if n < len2:
for j in range(n+1):
result.append(vec1[i+j])
result.append(vec2[j])
else:
for j in range(n+1):
if j == vec2[-1]:
for k in range(n):
result.append(vec1[i+k])
result.append(vec2[k])
else:
result.append(vec1[i+j])
result.append(vec2[j])
else:
result.append(vec1[i])
result.append(vec2[i])
result.pop(-1)
if len2 > len1:
for i in range(min_len):
result.append(vec1[i])
result.append(vec2[i])
result.pop(-1)
return result
My main struggle is within the case where n is not less than len2. I don’t know how to make python iterate over the second list more than once until the first list is exhausted. However, if someone knows a better method that accomplishes the same thing as Mathematica’s Riffle function in Python, please let me know.
Use itertools.cycle()
to keep repeating vec2
as needed. Then use zip()
to loop over the two lists in parallel.
from itertools import cycle
def riffle(vec1, vec2):
if len(vec2) == 0: # special case for empty second vector
return vec1[:1]
result = []
for x, y in zip(vec1, cycle(vec2)):
result.append(x)
result.append(y)
if len(vec2) != len(vec1):
result.pop() # remove last element
return result