为什么列表结果与预期不同?

Why does list turn out different than expected?

我有一个整数列表。然后我想更改列表,而不是它包含,让我们说连续四个 1:s,它应该说 [[4, 1]]。所以我为此做了一个函数,但我得到了意想不到的结果。

这是函数

compressed3 = []

def repeat_comp(data):
    rep = 1

    for i, item in enumerate(data):
        if i < len(data) - 1:
            if item == data[i + 1]:
                rep += 1

            else:
                compressed3.append([rep, data[i - 1]])
                rep = 1

        else:
            if item == data[i - 1]:
                rep += 1

            else:
                compressed3.append([rep, data[i - 1]])
                rep = 1

repeat_comp(compressed2)

这是compressed2列表

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

这里是函数的结果与预期结果的对比

# output of function
[[1, 2832], # why this? (this number is one less than the lenght of another list that has nothing with this list to do)
 [1, 0],
 [1, 1],
 [1, 2],
# excluded value here
 [4, 1],
 [1, 1], # why this?
 [1, 4]]

# expected result
[[1, 0],
 [1, 1],
 [1, 2],
 [1, 3],
 [4, 1],
 [1, 4]]

这很好地说明了为什么函数应该是 idempotent,也就是说,在给定相同输入的情况下,每次调用函数都应该产生相同的结果。通过将结果列表 compressed3 移到函数外部,调用者需要确定哪些调用会改变此全局变量;几乎不可避免地,会出现令人困惑的结果。

我会按如下方式编写函数,使用 itertools.groupby:

from itertools import groupby

def compress_runs(lst):
    return [[len(list(v)), k] for k, v in groupby(lst)]

if __name__ == "__main__":
    print(compress_runs([1, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6])) 
    # => [[3, 1], [2, 2], [2, 3], [1, 4], [2, 5], [1, 6]]

您只需更改代码中的两处即可获得预期结果:

def repeat_comp(data):
    rep = 1
    compressed3 = []

    for i, item in enumerate(data):
        if i < len(data) - 1:
            if item == data[i + 1]:
                rep += 1

            else:
                compressed3.append([rep, item])
                rep = 1

        else:
            if item == data[i - 1]:
                rep += 1

            else:
                compressed3.append([rep, item])
                rep = 1
    return compressed3

compressed3 列表移动到函数中并让函数 return 它,因此每次调用函数时 compressed3 都会被清除。然后,您可以将 returned 列表分配给另一个变量:

result = repeat_comp(compressed2)

我把data[i - 1]改成了item

print(result) 会给你 [[1, 0], [1, 1], [1, 2], [1, 3], [4, 1], [1, 4]]