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.

Asked By: ryan

||

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
Answered By: Barmar