为什么列表结果与预期不同?
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]]
我有一个整数列表。然后我想更改列表,而不是它包含,让我们说连续四个 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]]