递归比较两个列表
Posted
技术标签:
【中文标题】递归比较两个列表【英文标题】:comparing two lists recrusively 【发布时间】:2022-01-08 06:53:55 【问题描述】:我的教授给了我一个 python 任务来比较 2 个二维列表,如果列表中的所有对象都相似,则返回 True,否则返回 False。 列表的类型为 list[list[int]]。 这必须使用递归来完成。 我不允许使用循环或切片。 (但可以访问列表中的特定索引) 列表的内部划分可能不同,但只要列表中相似位置的所有元素相似,函数就会返回 True。 例如 - [[1], [2, 3, 4]] , [[1, 2], [3, 4]] - 函数将返回 true。 我希望细节清楚,谢谢!
我的问题是找到解决这个问题的方法:)
【问题讨论】:
实际上,这在 Python 中有点无意义,因为 Python 可以将嵌套列表与其==
运算符进行比较... - 你可以开玩笑地写def compare(lol1, lol2): return lol1 == lol2
- 这绝对是一个工作Python 中的解决方案 ;) .
这实际上是一个很棒的python作业!感谢分享。但是你有问题吗?
@Gwang-JinKim 我理解问题陈述的方式,你的“解决方案”根本行不通。
哈哈遗憾的是,我们的大多数任务都是毫无意义的,只是为了让我们无缘无故地努力工作......我只能使用 == 来比较列表中的 int 而不是列表本身 :(
我的意思是开玩笑——这种任务通常来自口语。但是对于递归,您必须比较列表的第一个元素(lisp 中的car
)和列表的其余部分(cdr
)-但问题是-您不允许使用切片...以及如何使用可以在不切片的情况下获取列表的其余部分吗? ...
【参考方案1】:
a1 = [[1], [2, 3, 4]]
a2 = [[1, 2], [3, 4]]
def get_next_indexes(i, j, a): # function for getting next indexes based on previous
return (i + 1, 0)if j >= len(a[i]) - 1 else (i, j + 1)
def compare_lists(i1, j1, i2, j2): # i1 and j1 - indexes for first array; i2 and j2 - indexes for second array
if i1 >= len(a1) or i2 >= len(a2):
print("Two lists are equal.")
exit(0)
if a1[i1][j1] != a2[i2][j2]:
print("Two lists are not equal.")
exit(0)
print(get_next_indexes(i1, j1, a1))
compare_lists(*get_next_indexes(i1, j1, a1), *get_next_indexes(i2, j2, a2))
compare_lists(0, 0, 0, 0)
【讨论】:
【参考方案2】:通常你对列表中的car
和cdr
(first
和rest
)执行l[0]
和l[1:]
。
这项任务最大的挑战是禁止切片。
但是有
first, *rest = your_list
有效!不仅不用切片,而且不用索引。
def first(l): # traditionally in Lisp languages `CAR`
car, *cdr = l
return car
def rest(l): # traditionally in Lisp languages `CDR`
car, *cdr = l
return cdr
def comp(lol1, lol2):
if len(lol1) == len(lol2) == 0: # recursion end condition
return True
# if first elements are lists, `comp`are the firsts and the rests
elif type(first(lol1)) == type(first(lol2)) == list:
return comp(first(lol1), first(lol2)) and \
comp(rest(lol1), rest(lol2))
# if first elements are atoms (non-lists), `==` the firsts and `comp`are the rest
else: # then the firsts are atoms!
return first(lol1) == first(lol1) and \
comp(rest(lol1), rest(lol2))
# traditionally in Lisp languages, you test not for list
# but for `atom` (whether the first elements of the lists are
# non-lists -> atomar). But `atom` is not that easy test in Python.
# so it is must more easy to ask whether both first elements are lists - and
# if not - then it is clear that the first elements of non-empty lists must be non-lists => atoms.
这适用于 Python3,但不适用于 Python2。
对于 Python2 和 Python3,您可以使用函数定义:
def first(l):
return (lambda x, *y: x)(*l)
def rest(l):
return (lambda x, *y: y)(*l)
单索引和.pop()
也许你老师的想法是:
def first(l):
return l[0]
def rest(l):
if l != []:
l.pop()
return l
else:
return []
# For definition of the `comp()` function see above
但是这个解决方案是有问题的,因为它改变了
输入列表,因为 Python 执行 call-by-reference
而不是 call-by-value
。为避免这种情况,必须首先对列表进行深度复制。可以通过切片对列表进行浅拷贝,但不允许切片...
喜欢:
q = [1, 2, [3, 4], [5, 6, 7], 8]
comp(q, q)
## True
# so far so good, but:
q
## []
【讨论】:
以上是关于递归比较两个列表的主要内容,如果未能解决你的问题,请参考以下文章