Python 更新函数参数中列表的范围

Python 更新函数参数中列表的范围,python,python-3.x,list,Python,Python 3.x,List,要解决的问题:定义一个Python函数remdup(l),该函数接受一个非空的整数列表l 并删除l中的所有重复项,只保留每个数字的最后一次出现。例如: 如果我们通过这个论点,那么remdup([3,1,3,5])应该会给我们一个结果[1,3,5] def remdup(l): for last in reversed(l): pos=l.index(last) for search in reversed(l[pos]): if s

要解决的问题:定义一个Python函数remdup(l),该函数接受一个非空的整数列表l 并删除l中的所有重复项,只保留每个数字的最后一次出现。例如: 如果我们通过这个论点,那么remdup([3,1,3,5])应该会给我们一个结果[1,3,5]

def remdup(l):
    for last in reversed(l):
        pos=l.index(last)
        for search in reversed(l[pos]):
            if search==last:
                l.remove(search)

    print(l)


remdup([3,5,7,5,3,7,10])

# intended output [5, 3, 7, 10]

在循环的第4行中,我希望反向函数检查除索引[last]之外的每个数字,但如果我使用上面代码中的方法,它将取pos处的值,而不是索引号。如何解决这个问题?您需要反转整个切片,而不仅仅是一个元素:

        for search in reversed(l[:pos]):
请注意,在迭代时修改列表可能会遇到问题。看


我花了几分钟才弄明白这个笨拙的逻辑。相反,您需要列表的其余部分:

    for search in reversed(l[pos+1:]):
输出:

[5, 3, 7, 10]

您的原始算法可以改进。嵌套循环会导致一些不必要的复杂性

或者,您可以执行以下操作:

def remdup(l):
seen = set()
for i in reversed(l):
    if i in seen:
        l.remove(i)
    else:
        seen.add(i)

print(l)
我使用“seen”集合来跟踪已经出现的数字

但是,这将更有效率:

def remdup(l):
seen = set()
for i in range(len(l)-1, -1, -1):
    if l[i] in seen:
        del l[i]
    else:
        seen.add(l[i])

print(l)

在第二个算法中,我们使用一个范围以相反的顺序迭代列表,然后删除“seen”中已经存在的任何项。我不确定reversed()和remove()的实现是什么,所以我不能说对时间/空间复杂性的确切影响。但是,可以清楚地看到第二种算法中发生了什么,因此我认为这是一种更安全的选择。

这是一种相当低效的实现方法:

def remdup(l):
    i = 0
    while i < len(l):
        v = l[i]
        scan = i + 1
        while scan < len(l):
            if l[scan] == v:
                l.remove(v)
                scan -= 1
                i -= 1
            scan += 1
        i += 1

l = [3,5,7,5,3,7,10]
remdup(l)
print(l)
def remdup(l):
i=0
而我
它基本上遍历列表(按
i
索引)。对于每个元素,它在列表中向前扫描匹配项,对于找到的每个匹配项,它删除原始元素。由于删除元素会移动索引,因此在继续之前会相应地调整其两个索引


它利用了内置的“从列表中删除第一个值等于x的项”。

这里是另一个解决方案,向后迭代并弹出以前遇到的项的索引:

def remdup(l):
    visited= []
    for i in range(len(l)-1, -1, -1):
        if l[i] in visited:
            l.pop(i)
        else:
            visited.append(l[i])
    print(l)

remdup([3,5,7,5,3,7,10])
#[5, 3, 7, 10]
使用字典:

def remdup(ar):
    d = {}
    for i, v in enumerate(ar):
        d[v] = i
    return [pair[0] for pair in sorted(d.items(), key=lambda x: x[1])]


if __name__ == "__main__":
    test_case = [3, 1, 3, 5]
    output = remdup(test_case)
    expected_output = [1, 3, 5]
    assert output == expected_output, f"Error in {test_case}"

    test_case = [3, 5, 7, 5, 3, 7, 10]
    output = remdup(test_case)
    expected_output = [5, 3, 7, 10]
    assert output == expected_output, f"Error in {test_case}"
解释

  • 在字典中保留数字每次出现的最后一个索引。因此,我们的存储方式如下:
    dict[number]=last\u occurrence
  • 按值对字典排序,并使用列表理解从字典的键创建新列表

    • 除了其他正确答案,这里还有一个

      from iteration_utilities import unique_everseen,duplicates
      import numpy as np
      list1=[3,5,7,5,3,7,10]
      dup=np.sort(list((duplicates(list1))))
      list2=list1.copy()
      for j,i in enumerate(list2):
          try:
              if dup[j]==i:
                 list1.remove(dup[j])
          except:
              break
      print(list1)
      

      这一行怎么样:(转换成函数对于练习来说很容易)

      如果不需要新列表,可以改为:

      lst[:] = list(dict.fromkeys(reversed(lst)))[::-1]
      

      它不起作用,但它以任何方式使用最后一个元素,而且它更易于用我的代码实现。非常感谢。真的很感谢你这么说很高兴听到你这么说。但是,请查看迭代和删除的链接,并考虑转换逻辑。您所做的有点敏感,即使您正在为list.Hmmm使用临时值。可以我一定会抢的。耶!成功了。但是你能解释一下米德解释的答案吗。有几十种方法可以实现你的目标。这只是一个例子!哦。是的,还有其他的方法。我是初学者。
      lst[:] = list(dict.fromkeys(reversed(lst)))[::-1]