从给定列表创建新列表,以便新列表可以标记给定列表中的连续重复

时间:2019-04-17 17:22:24

标签: python python-3.x itertools

我有一长串数字(数十万项),我想创建一个大小相等的新列表,以找出连续重复数字的位置。新列表将具有0和1值,因此对于连续的重复索引,新列表将具有1,其余索引将具有0值。

如果在pandas列中也有帮助的话。

对给定列表和结果数组进行采样。列表也可以具有浮点值。

given_array = [1, 2, 3, 5, 5, 5, 5, 0, -2, -4, -6, -8, 9, 9, 9]

result_array = [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]

我在下面给出了我的代码的一个小示例。

import itertools    

def list_from_count(list_item):
    """
    Function takes an iterator and based on the length of the item
    returns 1 if length is 1 or list of 0 for length greater than 1
    """
    if len(list(list_item[1])) == 1:
        return 1
    else:
        return [0] * len(list(list_item[1]))

r0 = list(range(1,4))
r1 = [5]*4
r2 = list(range(0,-10,-2))
r3 = [9]*3
r = r0 + r1 + r2 + r3


gri = itertools.groupby(r)
res = list(map(list_from_count,gri))

print ("Result",'\n',res)

结果

[1, 1, 1, [], 1, 1, 1, 1, 1, []]

谢谢!

4 个答案:

答案 0 :(得分:3)

如果组的长度大于1,则可以使用itertools.groupby并输出重复的1 s。

from itertools import groupby

result_array = []
for _, g in groupby(given_array):
    size = sum(1 for i in g)
    if size == 1:
        result_array.append(0)
    else:
        result_array.extend([1] * size)

或具有列表理解:

result_array = [i for _, g in groupby(given_array) for s in (sum(1 for i in g),) for i in ([0] if s == 1 else [1] * s)]

result_array变为:

[0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]

答案 1 :(得分:1)

您两次使用len(list(list_item[1]))。第一次使用它时,它将处理迭代器中的所有项目。当您第二次调用它时,迭代器已全部用尽,因此它返回0,这就是为什么您得到零元素列表的原因。

您需要在第一次将长度保存在变量中:

def list_from_count(list_item):
    l = len(list(list_item[1]))
    if l == 1:
        return [0]
    else:
        return [1] * l

您还需要从该函数一致地返回一个列表,然后才能将所有结果连接起来,这样就不会混用数字和子列表。

res = []
for el in gri:
    res += list_from_count(el)
print(res)

答案 2 :(得分:1)

这种情况更类似于run length encoding问题。考虑more_itertools.run_length

给出

import more_itertools as mit


iterable = [1, 2, 3, 5, 5, 5, 5, 0, -2, -3, -6, -8, 9, 9, 9]

代码

result = [[0] if n == 1 else [1] * n for _, n in mit.run_length.encode(iterable)]
result
# [[0], [0], [0], [1, 1, 1, 1], [0], [0], [0], [0], [0], [1, 1, 1]]

现在只需将子列表(无论您希望如何)展平为一个列表:

list(mit.flatten(result))
# [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]

详细信息

mit.run_length.encode通过产生( value #repititions )的元组来压缩可迭代对象,例如:

list(mit.run_length.encode("abaabbba"))
# [('a', 1), ('b', 1), ('a', 2), ('b', 3), ('a', 1)]

我们的理解会忽略该值,使用重复n并创建[0][1] * n的子列表。

注意:more_itertools是第三方软件包。通过> pip install more_itertools安装。

答案 3 :(得分:0)

使用PANDAS shift运算符创建向量移位1元素。比较原始。这将为您提供True / False值的向量,显示元素与上一个元素匹配的位置。在该列表下进行线性搜索,以在前面扩展一个元素:将[False,True]更改为[True,True]。转换为int,您将获得指定的列表。