【问题标题】:How to sort this 3D data in python?如何在 python 中对这个 3D 数据进行排序?
【发布时间】:2020-02-20 12:08:14
【问题描述】:

我有以下数据:

  1. 每个组内都有宽度
  2. 每个宽度都有一米

例如:

 Group 1:
|Width|Meters|
--------------
|144  |500   |
--------------
|142  | 450  |

Group 2:
|Width|Meters|
--------------
|140  |500   |
--------------
|156  | 450  |

现在我需要创建一个排序算法,它将首先选择米总和更大的组,然后按降序对宽度进行排序 我不知道如何存储这些数据?它应该是字典还是 3d 数组?还是三个列表? 并且使用正确的数据结构,我该如何对其进行实际排序。即使您引导我走向正确的道路,我也不会要求完整的代码,我会找到自己的方式。谢谢

【问题讨论】:

  • 在不了解更多问题的情况下很难说。字典是清晰和优雅代码的良好起点。如果速度很关键,numpy 数组可能会很有用。我会说从嵌套的 dicts 开始(一个 dict 包含组,每个组本身就是一个 dict 等),看看它是否适合你。
  • 您只需要对总和最大的组进行排序,或者您需要按米的总和对组的集合进行排序,然后为每个组对宽度-米对进行排序?
  • @MarcoZamboni - 后者,需要按 sum 对组的集合进行排序,选择总和较大的一组,然后对宽度米进行排序。
  • @JussiNurminen 我可以提供更多信息吗?我会看看嵌套的字典。
  • @JussiNurminen 将其视为组的一个“for 循环”,在其中一个“for 循环”用于测量将用于计算的米的宽度。该算法应该从具有最高米和最大宽度的组开始,因此进行排序。我可以提供任何其他信息以使其变得更好吗?

标签: python algorithm numpy sorting data-structures


【解决方案1】:

使用 numpy:

#                 Width Meters   
data = np.array([[[144, 500],    # Group 1
                  [142, 450]],

                 [[140, 500],    # Group 2
                  [156, 460]]])

# Pick the group with the largest sum of Meters
group_index = np.argmax(data.sum(1)[:,1])
print(f'Group with the largest sum of Meters: Group {group_index + 1}')

result = data[group_index]

# sort by Width in descending order
result = result[np.argsort(result[:,0])[::-1]]

结果:

array([[156, 460],
       [140, 500]]) 

编辑:

data = np.array([[[144, 500],
                  [142, 450],
                  [150, 300]],  

                 [[140, 500],
                  [156, 460],
                  [145, 300]],

                 [[170, 500],
                  [180, 455],
                  [160, 300]]])

# Sort Groups by the sum of Meters
group_inds = np.argsort(data.sum(1)[:, 1])[::-1]
result = data[group_inds]

# Sort by Width in each group
result = result[np.arange(data.shape[0])[:, None], 
                np.argsort(result[..., 0], axis=1)[:,::-1]]

结果:

array([[[156, 460],
        [145, 300],
        [140, 500]],

       [[180, 455],
        [170, 500],
        [160, 300]],

       [[150, 300],
        [144, 500],
        [142, 450]]])

【讨论】:

  • 谢谢.. 结果可以是array([[156,460],[140,500]],[[140,500],[156,450]]) 吗?
  • @Jhonty4 是的,它可以。其实我原来的解决方案就是这样。它按米的最大总和对组进行排序,然后按宽度对行进行排序。我稍后会发布。
  • 对不起,请忽略上面的评论。我需要得到完整的数组作为结果,因为我需要遍历它。结果可以是:array([[156,460],[140,500]],[[144,500],[142,450]]) ?
  • @Jhonty4 好的,完成!我使用了三个组的不同示例。这是你需要的吗?
【解决方案2】:

排序算法可以通过分而治之的方法简单地创建。
事实上,对组进行排序和对(宽度,米)对进行排序是我们可以独立解决的不同问题。

数据结构的选择取决于您,取决于您的需要;例如,一个组可以是一个命名元组(宽度,米)的列表,或者如果您需要更高的效率,则可以使用 2d numpy 数组 Nx2。
如果您不需要命名组,则各种组的容器可以是列表(或 numpy 数组)、(名称、数据)元组列表或字典名称-> 数据;没有严格的规则,每种可能性都有优点和缺点(例如,在 (name, data) 的列表中可能很难有效地找到知道名称的数据,但很容易排序,1 LOC。虽然字典提供了一种很好的数据检索方式,但排序可能会比较麻烦)。

这是一个配置示例,我使用字典名称->数据来存储各种组(不会排序!);一个列表,其中仅包含按排序方式的组名称;数据的命名元组列表。
通过这种方式,我可以轻松检索数据,如果我想查看顺序,我可以访问名称列表,然后访问数据字典

from collections import namedtuple

GroupData = namedtuple("GroupData", ["Width", "Meters"])

# Container of groups:
groups = {"Group 1": [GroupData(144, 500), GroupData(142, 650)],
          "Group 2": [GroupData(140, 800), GroupData(156, 450)]}

# Sorted list of names of groups
sorted_groups = sorted([name for name in groups], 
                        key=lambda name:sum(data.Meters for data in groups[name]),
                        reverse=True)                       

# Sort each group
for group_data in groups.values():
    group_data.sort(key=lambda data:data.Width, reverse=True)

print(groups)
print(sorted_groups)

【讨论】:

  • 谢谢,太好了。您能否就如何访问/迭代此列表中的元素提供任何提示?
  • 我尝试过并且能够通过以下方式获取最大组中第一个宽度的米: print((groups[sorted_groups[0]][0])[1])
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
  • 2014-01-29
  • 2014-07-14
  • 2010-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多