有唯一列表时如何停止该功能?

时间:2019-04-14 04:21:01

标签: python

我尝试了一个可以删除列表中两个相邻重复项的函数。删除任何新的重复对,该功能将继续进行,直到列表中没有更多重复对为止。

我遇到一个问题,即一旦我有了一个没有相邻重复项的列表,该如何告诉该函数停止。

def removepair(no):
  i = 1
  if len(no) == 0 or len(no) == 1:
    return no 
  while i < len(no):   
    if no[i] == no[i-1]:
      no.pop(i)
      no.pop(i-1)
      i -= 1  
    i += 1
  return removepair(no)

到目前为止,该函数在删除后将返回0或单个元素:

  

输入:[1、2、2、1]输出:[]

  

输入:[4,4,4,4,4]输出:[4]

但是问题是,一旦它具有一个包含多个元素的列表,我不知道如何停止递归函数:

  

输入:[1,2,3,3,2,1,5,6,7]
  预期输出:[5,6,7]

3 个答案:

答案 0 :(得分:1)

如果我们仔细地设置递归,我们也许可以避免布尔标志和计数器:

def removepairs(numbers):

    if not numbers:  # base case #1, empty
        return numbers

    first, *second_on = numbers

    if not second_on:  # base case #2, one element
        return numbers

    second, *third_on = second_on

    if first == second:
        return removepairs(third_on)

    result = [first] + removepairs(second_on)

    if result == numbers:
        return numbers  # base case #3, no change!

    return removepairs(result)

print(removepairs([1, 2, 3, 3, 2, 1, 5, 6, 7]))

输出

> python3 test.py
[5, 6, 7]
> 

答案 1 :(得分:1)

如果不需要递归函数,则可以使用以下代码轻松完成。我已经评论了印刷声明。

def removepair(input_list):
    unique_input_list = list(set(input_list))
    output_list = list(x for x in unique_input_list if input_list.count(x)%2 == 1)
    #print('Input List: ', input_list)
    #print('Output list: ', output_list)
    return output_list

Input List:  [1, 2, 3, 3, 2, 1, 5, 6, 7]
Output list:  [5, 6, 7]

Input List:  [4, 4, 4, 4, 4]
Output list:  [4]

Input List:  [1, 2, 3, 3, 2, 1]
Output list:  []

答案 2 :(得分:1)

当没有元素从列表中弹出时,而不是在列表几乎为空时,您的递归应该停止:

def removepair(no):
    L = len(no)
    if L <= 1:
        return no
    i = 1
    while i < len(no):
        if no[i] == no[i-1]:
            no.pop(i)
            no.pop(i-1)
            i -= 1
        i += 1
    if len(no) < L:
        # elements where popped since the list len has decreased
        return removepair(no)
    else:
        return no

您的代码难以理解,因为它混合了递归和副作用。通常,您可以使用其中一个。在这里,您可以将您的递归调用替换为一段时间:

def removepair(no):
    while True:
        L = len(no)
        if L <= 1:
            return no
        i = 1
        while i < len(no):
            if no[i] == no[i-1]:
                no.pop(i)
                no.pop(i-1)
                i -= 1
            i += 1
        if len(no) == L: # no elements where popped
            return no

但这不是真正的Pythonic,我认为您不应在函数内部修改参数no,而应返回一个新列表。为什么不遍历该列表并且不复制结果中的重复项?

def removepair(no):
    ret = []
    for e in no:
        if ret and e == ret[-1]: # current element is the same as the last element
            ret.pop()
        else:
            ret.append(e)
    return ret

或折叠:

def removepair(no):
    import functools
    return functools.reduce(lambda acc, x: acc[:-1] if acc and acc[-1]==x else acc+[x], no, [])