【问题标题】:function that replaces consecutive duplicate elements of list with single element用单个元素替换列表中连续重复元素的函数
【发布时间】:2020-04-06 11:38:24
【问题描述】:

我尝试了什么:

def compress(l):
    i = 0
    while i < len(l)-1:
        if l[i] == l[i+1]:
            del l[i]
        else:
            i = i+1
l = [1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5]
compress(l)

由于我刚刚开始,我还不知道 python 中的很多函数,所以我想用基本的方法来做这件事,即使用 for 和 while 循环以及一些列表方法。 我究竟做错了什么? 任何其他方法 另一个我尝试了这个有什么问题:

def compress(l):
    for i in l:
        if l[i] == l[i+1] and i != (len(l) - 1):
            l.pop(l[i])

        print(l)
l = [1,1,1,1,2,2,2,2,2,2,3,3,3,4,5,6,7,8]
compress(l)

这给了我输出:

[1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 3, 3, 3, 4, 5, 6, 7, 8]
[1, 1, 2, 3, 3, 3, 4, 5, 6, 7, 8]

【问题讨论】:

    标签: python python-3.x list loops


    【解决方案1】:

    您的第一次尝试似乎没有做任何任何事情错误(a),除了您没有打印压缩列表这一事实。这可以通过将其添加为最后一行来解决:

    print(l)
    

    此时,您应该会看到:

    [1, 2, 3, 4, 5]
    

    像我一样。


    您的 second 尝试是有问题的 - 当您修改您正在迭代的列表时,这很常见。因为迭代有效地基于索引进行检查,所以在当前点之前插入项目可能会导致项目被处理两次。此外,在当前点或之前删除项目可能会导致项目根本不被处理。

    后一种情况是您第二次尝试时发生的情况。


    (a) 您可能会为变量选择比l 更具描述性的名称,但这只是我的偏好。

    【讨论】:

    • 其实我刚开始的时候,我通常会用简短的​​形式给出变量名。从现在开始我将是描述性的
    • 我没有看到为什么函数参数在这里需要一个更具描述性的名称的任何特殊原因。它不像需要区分其他值。不过,由于其他原因,l 是一个错误的变量名。 (l1I 看起来都很相似,具体取决于您的字体。)
    • @chepner: def compress(l): 给出了 no 指示应该传递的内容,因此,除非您已经知道,否则您必须检查代码。像listToRemoveConsecutiveDupesFrom 这样的东西,尽管冗长荒谬,仍然是一个更好的名字。如果有 cmets,也许可以使用较短的名称(由于您指出的原因,仍然不是 l),但我倾向于使用代码来告诉我需要什么,因为代码和 cmets 有时会随着时间的推移而出现分歧。跨度>
    • 这就是文档字符串(或其他文档)的用途。
    • @chepner:因此我的评论“仅仅是因为代码和 cmets 有时会随着时间的推移而分歧”:-) 假设它们保持同步,我对此没有任何问题。
    【解决方案2】:

    由于您要求使用其他方法,因此应该指出从列表中重复删除会导致性能不佳,因为每次删除都必须移动所有尾部元素。从头开始构建压缩列表成本更低,切片分配允许您改变原始列表。使用基本的循环和列表方法,我会这样做:

    def compress(l):
        new_l = l[:1]
        for x in l:
            if x != new_l[-1]:
                 new_l.append(x)
        l[:] = new_l
    

    对于使用一些更高级方法 (itertools.groupby) 的单行替代方案,您可以这样做:

    from itertools import groupby
    
    def compress(l):
        l[:] = [k for k, _ in groupby(l)]
    

    【讨论】:

      【解决方案3】:

      你不需要那么努力地删除列表中的重复元素:

      print(list(set(l)))
      

      这将删除列表中的所有重复元素。

      【讨论】:

      • 这是一个简洁的好答案,但它可能不是所需要的(尽管与 OP 核实)。该问题要求删除连续的重复项,但这既会删除非连续的重复项,也会得到可能不同的顺序。换句话说,[1, 1, 2, 2, 1, 1] 可能会变成[2, 1]
      • sorted(set(x), key=x.index) 如果订单很麻烦,这将解决问题。
      • 来自 itertools 的 groupby 将是一个选项。 @Python hub,paxdiabli 列表应该导致 [1,2,1] - 你的给出 [1,2] 或 [2,1] - 连续 1 的秒数也通过使用 set 消除。
      • 是的,在这种情况下,我们必须使用 itertools 中的 groupby,但为了消除重复元素,我们可以使用 set()。感谢您为我提供了一些知识。
      猜你喜欢
      • 2019-01-11
      • 1970-01-01
      • 2021-02-07
      • 2021-05-19
      • 1970-01-01
      • 2020-01-25
      • 2018-11-13
      • 2021-03-03
      • 1970-01-01
      相关资源
      最近更新 更多