在 python 中快速排序非常长的整数列表

sort very long list of integers quickly in python

我有一个包含几亿个 np.uint8 元素的向量。它们的值范围仅为 0 到 255。

我需要对这个列表进行排序,我认为它应该比快速排序处理得更快。我想我可以为所有值“0”找到索引并将它们放在前面,然后为所有值“1”找到索引并将它们放在最后一个插入之后,然后继续进行直到完成。这将是 unique 和 sort 的突变后代,带有一些索引并且应该工作得非常快。

是否有一个内置程序可以像 "C" 这样快速、正确地完成此操作,而无需我自己制作它?你能指给我看吗?

假设作为我实际问题的 "toy",我想对 mandrill image 的 100 兆像素版本的每种颜色 (rgb) 的强度值进行排序,其中每种颜色都是转换为一个非常长的 uint8 值向量。如果我要在 python?

中计算排序方法之间的差异,这将是合理的计算

您可能会发现 numpy.bincount 就是您所需要的。它计算数据中每个整数出现的次数。

例如,这里有一些随机的无符号 8 位整数:

In [100]: np.random.seed(8675309)                                                                                                                                                                      

In [101]: r = np.random.gamma(9, scale=8.5, size=100000).astype(np.uint8)                                                                                                                              

In [102]: r.min(), r.max()                                                                                                                                                                             
Out[102]: (11, 242)

使用 bincount 计算整数:

In [103]: b = np.bincount(r, minlength=256)                                                                                                                                                            

In [104]: b                                                                                                                                                                                            
Out[104]: 
array([   0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
          1,    1,    3,    1,    5,   13,    9,   17,   24,   31,   27,
         41,   55,   63,   96,  131,  146,  178,  210,  204,  268,  297,
        308,  367,  422,  480,  512,  584,  635,  669,  671,  759,  830,
        885,  934,  955, 1025, 1105, 1146, 1145, 1344, 1271, 1353, 1300,
       1456, 1419, 1451, 1504, 1499, 1561, 1600, 1509, 1678, 1621, 1643,
       1633, 1616, 1574, 1677, 1664, 1682, 1625, 1608, 1581, 1598, 1575,
       1583, 1524, 1493, 1381, 1448, 1399, 1422, 1249, 1322, 1225, 1278,
       1174, 1246, 1128, 1161, 1077,  999, 1033,  980,  981,  897,  917,
        880,  813,  779,  774,  697,  716,  651,  612,  657,  592,  556,
        497,  482,  474,  484,  445,  411,  399,  354,  368,  363,  342,
        313,  301,  293,  263,  241,  249,  244,  196,  215,  182,  189,
        172,  161,  139,  143,  142,  120,  121,  104,  103,  112,   88,
         82,   88,   67,   60,   83,   57,   63,   59,   50,   52,   55,
         40,   34,   34,   43,   35,   33,   28,   24,   26,   20,   18,
         21,   26,   30,   17,   15,   12,   17,   11,    7,    6,   16,
          8,    3,    4,   12,    9,    6,    5,    8,   10,    7,    1,
          4,    8,    5,    3,    2,    1,    0,    1,    1,    0,    1,
          0,    0,    4,    2,    2,    0,    0,    2,    0,    1,    1,
          1,    4,    0,    0,    0,    0,    0,    0,    0,    0,    2,
          1,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,
          0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
          1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0])

因此 0 在 r 中出现 0 次,13 出现 3 次,依此类推:

In [105]: b[0], b[13]                                                                                                                                                                                  
Out[105]: (0, 3)

您可以在不使用 bincount 和 repeat 进行排序的情况下执行此操作:

In [11]: a = np.bincount(np.array([71, 9, 1, 2, 3, 4, 4, 4, 8, 9, 9, 71], dtype=np.uint8), minlength=256)

In [12]: np.repeat(np.arange(256, dtype=np.uint8), a)
Out[12]: array([ 1,  2,  3,  4,  4,  4,  8,  9,  9,  9, 71, 71], dtype=uint8)

如果您只需要排序的 ,那么 bincount 确实是可行的方法。但是,如果你需要的是更多的argsort-like,比如你需要co-sort一些其他相同长度的数组,那么你可以使用this Q&A它比较各种方法,其中一些是很多比 'naive' argsort.