简体   繁体   中英

Create a list of pairs from two lists using recursion

I need to create a function that takes two lists as arguments and returns a list of the pairs of the elements in the two lists using recursion in python 3.x.

The input create_all_pairs([1,2], [3,4]) should give me :

[(1,3), (1,4), (2,3), (2,4)] .

I have created this function in 3 differen ways: using for-loops, using while-loops and using list comprehension.

def create_all_pairs_for(xs, ys):
    lst = []
    for x in xs:
        for y in ys:
            lst.append((x,y))
    return lst
def create_all_pairs_while(xs, ys):
    lst = []
    xscount = 0
    yscount = 0
    while xscount < len(xs):
        while yscount < len(ys):
            lst.append((xs[xscount], ys[yscount]))
            yscount += 1
        xscount += 1
        yscount = 0
    return lst
def create_all_pairs_listcomp(xs, ys):
    lst = [(a,b) for a in xs for b in ys]
    return lst

How can i write this function using recursion? This is what i have got so far, but i feel completely lost.

def create_all_pairs_rec(xs, ys):
    if not xs:
        return []
    else:
        return list(map(create_all_pairs_rec(xs, ys)), ys)

The following would be a recursive implementation:

def create_all_pairs(xs, ys):
    if not (xs and ys):
        return []
    return [(xs[0], y) for y in ys] + create_all_pairs(xs[1:], ys)

While this is a bit of cheat, as it only uses recursion to reduce the xs , here is a true recursive divide'n'conquer solution that decreases the problem size recursively for both xs and ys :

def create_all_pairs(xs, ys):
    if not (xs and ys):  # base case 1: any empty list
        return []
    if len(xs) == len(ys) == 1:  # base case 2: two singleton lists
        return [(xs[0], ys[0])]
    mid_x, mid_y = len(xs) // 2, len(ys) // 2
    return create_all_pairs(xs[:mid_x], ys[:mid_y]) + create_all_pairs(xs[:mid_x], ys[mid_y:]) + \
           create_all_pairs(xs[mid_x:], ys[:mid_y]) + create_all_pairs(xs[mid_x:], ys[mid_y:])

>>> create_all_pairs([1, 2], [3, 4])
[(1, 3), (1, 4), (2, 3), (2, 4)]
>>> create_all_pairs([1, 2, 3], [3, 4, 5])
[(1, 3), (1, 4), (1, 5), (2, 3), (3, 3), (2, 4), (2, 5), (3, 4), (3, 5)]
find_all_pairs(xs,ys,ret):
    if xs == []: #basecase
        return ret #return the list we built
    else:
        left = xs.pop() #we take an element out of the left list
        for right in ys: #for every element in the right list
            ret.append((left,right)) #we append to the list were building a (left,right) tuple
         return find_all_pairs(xs,ys,ret) #call the function again with the decremented xs and the appended ret

All pairs is the same as the cartesion product.

We can adapt this answer for using recursion to compute cartesion product: Cross product of sets using recursion (which has a good explanation)

An advantage of this function is that it works for an arbitrary number of lists (ie 1, 2, 3, etc.).

def create_all_pairs(*seqs):
    if not seqs:
        return [[]]
    else:
        return [[x] + p for x in seqs[0] for p in create_all_pairs(*seqs[1:])]

print(create_all_pairs([1,2], [3,4]))

Output

[[1, 3], [1, 4], [2, 3], [2, 4]]

Another recursive implementation, which also adds entries in a more sequential order to the final list of pairs, as compared to the answer above:

def create_all_pairs(list1, list2, resulting_list, index1=0, index2=0):

    if index1 < len(list1) and index2 < (len(list2)-1):
        resulting_list.insert(0, create_all_pairs(list1, list2, resulting_list, index1, index2+1))

    elif index1 < (len(list1)-1) and index2 >= (len(list2)-1):
        resulting_list.insert(0, create_all_pairs(list1, list2, resulting_list, index1+1, 0))

    if index1 == 0 and index2 == 0:
        resulting_list.insert(0, (list1[index1], list2[index2]))

    return (list1[index1], list2[index2])

resulting_list = list()
create_all_pairs([1, 2, 3], [3, 4, 5], resulting_list)

print("Resulting list is:", resulting_list)

Result:

Resulting list is: [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]
def all_pairs(x, y):
    return x and y and [(x[0], y[0])] + all_pairs(x[:1], y[1:]) + all_pairs(x[1:], y)

Based on @schwobaseggl's "true recursive" solution, just splitting differently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM