按自定义顺序排序列表

Posted

技术标签:

【中文标题】按自定义顺序排序列表【英文标题】:Sort List by custom order 【发布时间】:2021-04-02 13:42:08 【问题描述】:

给出一个列表,例如

[id: 4, id: 5, id: 4, id: 7, id: 6, id: 4, id: 5, id: 7]

并给出另一个列表

[5, 7, 6, 4]

如何根据第二个列表的值对第一个列表进行排序?

(即获得

[id: 5, id: 5, id: 7, id: 7, id: 6, id: 4, id: 4, id: 4]

结果)

【问题讨论】:

【参考方案1】:

你可以试试这样的:

void main() 
  List<Map<String, dynamic>> list = [
    "id": 4,
    "id": 5,
    "id": 4,
    "id": 7,
    "id": 6,
    "id": 4,
    "id": 5,
    "id": 7
  ];

  List<int> orderBy = [5, 7, 6, 4];

  List sorted = [];

    orderBy.forEach((val) => list
      .forEach((ele) => ele.values.first == val ? sorted.add(ele) : ""));

  
  print(sorted);

【讨论】:

这很好而且很紧凑,但是没有尽可能的节省时间。这是 O(m * n),其中 m 是要排序的列表的长度,n 是要排序的列表的长度。这可能已经足够好,但这也可以在 O(m + n) 时间内完成(以更多空间为代价),如果列表非常大,这可能很重要。 我要更改已接受的答案,因为我使用的是@jamesdlin 答案,希望没问题【参考方案2】:

我首先会构建一个逆映射,将 ID 值映射到具有该 ID 的所有条目的列表。从那里可以直接遍历指定所需顺序的第二个列表,从逆映射中查找条目,然后将结果拼接在一起:

void main() 
  var items = <Map<String, int>>[
    'id': 4,
    'id': 5,
    'id': 4,
    'id': 7,
    'id': 6,
    'id': 4,
    'id': 5,
    'id': 7,
  ];

  var orderBy = [5, 7, 6, 4];

  var idToItems = <int, List<Map<String, int>>>;
  for (var item in items) 
    (idToItems[item['id']] ??= []).add(item);
  
  
  var sorted = <Map<String, int>>[
    for (var id in orderBy)
      ...idToItems[id],
  ];
  
  print(sorted);

这种方法稍微复杂一些,但它的时间复杂度应该是 O(m + n)(其中 m 是 items 的长度,n 是 orderBy 的长度):

构建逆映射 (idToItems) 需要 O(m) 时间。对于items 的 m 个元素中的每一个: 查找或插入idToItems,时间复杂度为 O(1)。 将该条目附加到具有相同 ID 的条目列表中,该 ID 应该是 O(1) 摊销。 迭代orderBy 是 O(n)。 将子列表整体拼接在一起需要 O(m)。

【讨论】:

谢谢陛下。目前不在我的办公桌前,但如果有问题,我会检查并提出问题。非常感谢您抽出时间来发帖。

以上是关于按自定义顺序排序列表的主要内容,如果未能解决你的问题,请参考以下文章

按自定义字典顺序对字符串进行排序

按自定义顺序对数组的php数组进行排序

在 Eloquent 中按自定义顺序对集合进行排序 [重复]

如何按自定义顺序对 JavaScript 中的数组进行排序? [复制]

PHP按自定义顺序对工作日和月份-年份数组进行排序

php 按自定义帖子类型获取帖子列表