首页 > 解决方案 > 排序多维列表 - Python

问题描述

我有一个 3d 列表或 numpy 数组列表,我需要按最小的第一项索引对其进行排序。这是我在这个程序上做的最后两个尝试。抱歉,我很确定这是一个简单/愚蠢的问题,但作为编程“思维方式”的新手,这对我来说有点难。 第一次尝试:

 lstsArray = [[[54,21,31], [1,2,3], [15,25,35]],
              [[12,22,32], [3,2,1], [16,26,36]],
              [[34,24,38], [0.1,1,1], [17,27,37]]]
 val = np.array(lstsArray)
 menor = 120e26
 for item in val:
     for i in item:
         if menor >= i[0] and i[0] >= min(i):
             menor = i[0]
 print(menor)
 lstA = list(val)
 a = sorted(lstA, key=itemgetter(menor))
 print(a)

第二次尝试

for i in val:
    for j in i:
        print(sorted((i), key =itemgetter(j[0])))

期望的输出

[[[0.1,1,1],[1,2,3],[3,2,1]],
 [[12,22,32],[15,25,35],[16,26,36]],
 [[17,27,37],[34,24,38],[54,21,31]]] 

标签: pythonnumpysorting

解决方案


您的列表和由它制成的数组。注意数组中的浮点数:

In [124]: lstsArray = [[[54,21,31], [1,2,3], [15,25,35]], 
     ...:               [[12,22,32], [3,2,1], [16,26,36]], 
     ...:               [[34,24,38], [0.1,1,1], [17,27,37]]]                                                         
In [125]: val=np.array(lstsArray)                                                                                    
In [126]: val                                                                                                        
Out[126]: 
array([[[54. , 21. , 31. ],
        [ 1. ,  2. ,  3. ],
        [15. , 25. , 35. ]],

       [[12. , 22. , 32. ],
        [ 3. ,  2. ,  1. ],
        [16. , 26. , 36. ]],

       [[34. , 24. , 38. ],
        [ 0.1,  1. ,  1. ],
        [17. , 27. , 37. ]]])

这是一个 (3,3,3) 形状的阵列。但是您的排序忽略了最初的 (3,3) 布局,所以让我们继续并重塑它:

In [133]: val = np.array(lstsArray).reshape(-1,3)                                                                    
In [134]: val                                                                                                        
Out[134]: 
array([[54. , 21. , 31. ],
       [ 1. ,  2. ,  3. ],
       [15. , 25. , 35. ],
       [12. , 22. , 32. ],
       [ 3. ,  2. ,  1. ],
       [16. , 26. , 36. ],
       [34. , 24. , 38. ],
       [ 0.1,  1. ,  1. ],
       [17. , 27. , 37. ]])

现在我们可以轻松地在第一列值上重塑。 argsort给出排序顺序:

In [135]: idx = np.argsort(val[:,0])                                                                                 
In [136]: idx                                                                                                        
Out[136]: array([7, 1, 4, 3, 2, 5, 8, 6, 0])
In [137]: val[idx]                                                                                                   
Out[137]: 
array([[ 0.1,  1. ,  1. ],
       [ 1. ,  2. ,  3. ],
       [ 3. ,  2. ,  1. ],
       [12. , 22. , 32. ],
       [15. , 25. , 35. ],
       [16. , 26. , 36. ],
       [17. , 27. , 37. ],
       [34. , 24. , 38. ],
       [54. , 21. , 31. ]])

并将其恢复为 3d:

In [138]: val[idx].reshape(3,3,3)                                                                                    
Out[138]: 
array([[[ 0.1,  1. ,  1. ],
        [ 1. ,  2. ,  3. ],
        [ 3. ,  2. ,  1. ]],

       [[12. , 22. , 32. ],
        [15. , 25. , 35. ],
        [16. , 26. , 36. ]],

       [[17. , 27. , 37. ],
        [34. , 24. , 38. ],
        [54. , 21. , 31. ]]])

或在列表显示中:

In [139]: val[idx].reshape(3,3,3).tolist()                                                                           
Out[139]: 
[[[0.1, 1.0, 1.0], [1.0, 2.0, 3.0], [3.0, 2.0, 1.0]],
 [[12.0, 22.0, 32.0], [15.0, 25.0, 35.0], [16.0, 26.0, 36.0]],
 [[17.0, 27.0, 37.0], [34.0, 24.0, 38.0], [54.0, 21.0, 31.0]]]

但如果列表只有一层嵌套:

In [140]: alist = val.tolist()                                                                                       
In [141]: alist                                                                                                      
Out[141]: 
[[54.0, 21.0, 31.0],
 [1.0, 2.0, 3.0],
 [15.0, 25.0, 35.0],
 [12.0, 22.0, 32.0],
 [3.0, 2.0, 1.0],
 [16.0, 26.0, 36.0],
 [34.0, 24.0, 38.0],
 [0.1, 1.0, 1.0],
 [17.0, 27.0, 37.0]]

python sorted 工作得很好:

In [142]: sorted(alist, key=lambda x:x[0])   # or itemgetter                                                                           
Out[142]: 
[[0.1, 1.0, 1.0],
 [1.0, 2.0, 3.0],
 [3.0, 2.0, 1.0],
 [12.0, 22.0, 32.0],
 [15.0, 25.0, 35.0],
 [16.0, 26.0, 36.0],
 [17.0, 27.0, 37.0],
 [34.0, 24.0, 38.0],
 [54.0, 21.0, 31.0]]

您有一个双重嵌套列表,但希望排序忽略一层这一事实使列表处理复杂化。这就是numpy重塑有很大帮助的地方。

现在我不会测试这些方法的相对速度。


推荐阅读