Python:将排序的重复值的单个数组转换为数组数组?

时间:2016-03-21 18:51:48

标签: python arrays numpy

我有一个带有一些重复值的排序数组。如何将这个数组转换成一个数组数组,子数组按值分组(见下文)?实际上,my_first_array有大约800万个条目,因此解决方案最好尽可能节省时间。

my_first_array = [1,1,1,3,5,5,9,9,9,9,9,10,23,23]

wanted_array = [ [1,1,1], [3], [5,5], [9,9,9,9,9], [10], [23,23] ]

4 个答案:

答案 0 :(得分:4)

itertools.groupby makes this trivial

import itertools

wanted_array = [list(grp) for _, grp in itertools.groupby(my_first_array)]

如果没有key函数,则只有yield个由相同值组合运行的组,因此您list - ify列表理解中的每一个;十分简单。您可以将其视为用于执行GNU工具包程序uniq和相关操作的Python内部API。

在CPython(引用解释器)中,groupby在C中实现,它以懒惰和线性方式运行;数据必须已经出现在与key函数匹配的运行中,因此排序可能会使它过于昂贵,但对于已经排序的数据,就像你拥有的那样,没有什么比这更有效了。

注意:如果输入可能是相同但不同的对象,则可能因内存原因将list(grp) for _, grp更改为[k] * len(list(grp)) for k, grp。前者将在最终结果中保留原始(可能是值但不是标识副本)对象,后者将从每个组中复制第一个对象,从而将每个组的最终成本降低到N引用的成本。单个对象,而不是对N1个对象之间的N个引用。

答案 1 :(得分:2)

我假设输入是一个NumPy数组,你正在寻找一个数组列表作为输出。现在,您可以将输入数组拆分为索引,其中这些移位(重复组具有边界)与np.split。要查找此类索引,有两种方法 - 使用np.unique将其可选参数return_index设置为True,将另一种方法与np.wherenp.diff组合使用。因此,我们将采用下面列出的两种方法。

使用np.unique -

import numpy as np

_,idx = np.unique(my_first_array, return_index=True)
out = np.split(my_first_array, idx)[1:]

使用np.wherenp.diff -

idx = np.where(np.diff(my_first_array)!=0)[0] + 1
out = np.split(my_first_array, idx)

示例运行 -

In [28]: my_first_array
Out[28]: array([ 1,  1,  1,  3,  5,  5,  9,  9,  9,  9,  9, 10, 23, 23])

In [29]: _,idx = np.unique(my_first_array, return_index=True)
    ...: out = np.split(my_first_array, idx)[1:]
    ...: 

In [30]: out
Out[30]: 
[array([1, 1, 1]),
 array([3]),
 array([5, 5]),
 array([9, 9, 9, 9, 9]),
 array([10]),
 array([23, 23])]

In [31]: idx = np.where(np.diff(my_first_array)!=0)[0] + 1
    ...: out = np.split(my_first_array, idx)
    ...: 

In [32]: out
Out[32]: 
[array([1, 1, 1]),
 array([3]),
 array([5, 5]),
 array([9, 9, 9, 9, 9]),
 array([10]),
 array([23, 23])]

答案 2 :(得分:0)

这是一个解决方案,虽然可能效率不高:

my_first_array = [1,1,1,3,5,5,9,9,9,9,9,10,23,23]
wanted_array = [ [1,1,1], [3], [5,5], [9,9,9,9,9], [10], [23,23] ]

new_array = [ [my_first_array[0]] ]
count = 0
for i in range(1,len(my_first_array)):
    a = my_first_array[i]
    if a == my_first_array[i - 1]:
        new_array[count].append(a)
    else:
        count += 1
        new_array.append([])
        new_array[count].append(a)

new_array == wanted_array  

答案 3 :(得分:0)

这是O(n):

a = [1,1,1,3,5,5,9,9,9,9,9,10,23,23,24]

res = []
s = 0
e = 0
length = len(a)
while s < length:
    b = []
    while e < length and a[s] == a[e]:
        b.append(a[s])
        e += 1
    res.append(b)
    s = e
print res