如何找到列表中值的连续长度的每个长度的数量?

时间:2019-08-28 20:43:04

标签: python

问题

给出一个1和0的序列(列表或numpy数组),如何找到值的相邻子序列数?我想返回类似JSON的字典。

示例

[0, 0, 1, 1, 0, 1, 1, 1, 0, 0]将返回

{
  0: {
        1: 1,
        2: 2
  },
  1: {
        2: 1,
        3: 1
  }

}

尝试

这是我到目前为止拥有的功能

def foo(arr):
    prev = arr[0]
    count = 1

    lengths = dict.fromkeys(arr, {})

    for i in arr[1:]:
        if i == prev:
            count += 1
        else:
            if count in lengths[prev].keys():
                lengths[prev][count] += 1
            else:
                lengths[prev][count] = 1

            prev = i
            count = 1

    return lengths

即使列表中出现的字典不同,它也会为0和1输出相同的字典。而且此函数未获取最后一个值。我该如何改善和修复它?另外,如果我的数据位于numpy数组中,numpy是否提供任何更快的方法来解决我的问题? (也许使用np.where(...)

1 个答案:

答案 0 :(得分:2)

您遇到了Ye Olde复制错误。让我们通过函数来​​显示问题,添加一行以检查列表中每个字典的对象ID:

lengths = dict.fromkeys(arr, {})
print(id(lengths[0]), id(lengths[1]))

输出:

140130522360928 140130522360928
{0: {2: 2, 1: 1, 3: 1}, 1: {2: 2, 1: 1, 3: 1}}

问题是您将相同字典作为每个键的初始值。当您更新其中任何一个时,都在更改它们都引用的 one 对象。

将其替换为显式循环-而不是可变函数参数-它将为每个dict条目创建一个新对象:

for key in lengths:
    lengths[key] = {}
print(id(lengths[0]), id(lengths[1]))

输出:

139872021765576 139872021765288
{0: {2: 1, 1: 1}, 1: {2: 1, 3: 1}}

现在您有了单独的对象。

如果您想要单线,请使用dict理解:

lengths = {key: {} for key in lengths}