【问题标题】:Create a list of pairs from two lists using recursion使用递归从两个列表创建对列表
【发布时间】:2020-04-08 05:10:58
【问题描述】:

我需要创建一个函数,它接受两个列表作为参数,并在 python 3.x 中使用递归返回两个列表中元素对的列表。

输入 create_all_pairs([1,2], [3,4]) 应该给我:

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

我用 3 种不同的方式创建了这个函数:使用 for 循环、使用 while 循环和使用列表推导。

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

如何使用递归编写此函数?这是我到目前为止所得到的,但我完全迷失了。

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

【问题讨论】:

  • 每个列表中的一个元素你会怎么做?
  • 您缺少递归步骤。您使用完全相同的参数一次又一次地调用递归函数。递归的想法是有一个减少步骤,这将导致你停止条件
  • 仅供参考,这已经由 itertools.product 实现。

标签: python list recursion tuples


【解决方案1】:

以下将是递归实现:

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)

虽然这有点作弊,因为它只使用递归来减少xs,但这是一个真正的递归分治解决方案,它递归地减少xs 和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)]

【讨论】:

  • 不知道为什么,感觉使用明确的for 是“作弊”。感觉create_all_pairs 应该以停止条件为return [(xs[0], ys[0])] 的方式实现(即停止条件是当我们有2 个单元素列表时)。当然代价会是更长的调用栈
  • @DeepSpace 我也有同感。添加了更真实的递归实现;)
  • 很好,甚至还有一个 shorter 调用堆栈。但是,结果顺序不同(可以通过不同的拆分来修复(如有必要))。
【解决方案2】:

所有对都与cartesion产品相同。

我们可以调整这个答案以使用递归来计算笛卡尔积:Cross product of sets using recursion(有一个很好的解释)

此函数的一个优点是它适用于任意数量的列表(即 1、2、3 等)。

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]))

输出

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

【讨论】:

  • @DeepSpace--谢谢,我的复制/粘贴/编辑周期中的错字。
【解决方案3】:

另一个递归实现,与上面的答案相比,它还以更顺序的顺序将条目添加到最终的对列表中:

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)

结果:

Resulting list is: [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5)]

【讨论】:

    【解决方案4】:
    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)
    

    基于@schwobaseggl 的“真正递归”解决方案,只是拆分方式不同。

    【讨论】:

      【解决方案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
      

      【讨论】:

      • 忘记返回函数调用我的错误
      • 请添加有关此代码作用的更多信息,而不仅仅是编写代码,谢谢
      猜你喜欢
      • 1970-01-01
      • 2017-12-08
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      • 2021-05-18
      • 2012-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多