简体   繁体   English

如何按 Dart 中的另一个列表正确排序列表

[英]How to properly sort list by another list in Dart

I have two lists, 1 is a list of Map items, and another list which is the order.我有两个列表,一个是 Map 项的列表,另一个是顺序列表。
I would like to sort the items based on their description attribute and compare them with the order list and have them inserted at the top.我想根据项目的描述属性对项目进行排序,并将它们与订单列表进行比较,并将它们插入顶部。

import 'package:collection/collection.dart';

void main() {
  List<String> order = [
    'top european',
    'top usa',
    'top rest of the world'
  ];

  List<Map> items = [
    {'id': 0, 'id2': 5, 'description': 'Top USA'},
    {'id': 2, 'id2': 2, 'description': 'Top A'},
    {'id': 3, 'id2': 0, 'description': 'Top Z'},
    {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
    {'id': 4, 'id2': 4, 'description': 'Top C'},
    {'id': 5, 'id2': 1, 'description': 'Top D'},
    {'id': 1, 'id2': 3, 'description': 'Top European'},
  ];
  
  //this works but adds the items at the end
  items.sort((a,b)  {
    return order.indexOf(a['description'].toLowerCase()) - 
      order.indexOf(b['description'].toLowerCase());
  });

  ///Results: print(items);
  // List<Map> items = [
  //   {'id': 2, 'id2': 2, 'description': 'Top A'},
  //   {'id': 3, 'id2': 0, 'description': 'Top Z'},
  //   {'id': 4, 'id2': 4, 'description': 'Top C'},
  //   {'id': 5, 'id2': 1, 'description': 'Top D'},
  //   {'id': 1, 'id2': 3, 'description': 'Top European'},
  //   {'id': 0, 'id2': 5, 'description': 'Top USA'},
  //   {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
  // ];
}

SOLUTION: I also tried this approach which is not ideal, but it works.解决方案:我也尝试过这种不理想的方法,但它有效。

List <Map> itemsOrder = items
  .where(
    (ele) => order.contains(ele['description'].toString().toLowerCase()))
  .toList();

itemsOrder.sort((a, b) {
  return order.indexOf(a['description'].toLowerCase()) -
    order.indexOf(b['description'].toLowerCase());
});

items.removeWhere(
  (ele) => order.contains(ele['description'].toString().toLowerCase()));

itemsOrder = itemsOrder.reversed.toList();

for (int i = 0; i < itemsOrder.length; i++) {
  items.insert(0, itemsOrder[i]);
}

///Results: print(items);
// List<Map> items = [
//   {'id': 1, 'id2': 3, 'description': 'Top European'},
//   {'id': 0, 'id2': 5, 'description': 'Top USA'},
//   {'id': 6, 'id2': 6, 'description': 'Top Rest of the world'},
//   {'id': 2, 'id2': 2, 'description': 'Top A'},
//   {'id': 3, 'id2': 0, 'description': 'Top Z'},
//   {'id': 4, 'id2': 4, 'description': 'Top C'},
//   {'id': 5, 'id2': 1, 'description': 'Top D'},
// ];

Ideally, I would like to use sortBy or sortByCompare but unfortunately, I cannot find a proper example or get a grasp of how to use it.理想情况下,我想使用sortBysortByCompare ,但不幸的是,我找不到合适的示例或无法掌握如何使用它。

The way I would fix this is to find the index of the description in the order list and if it cannot be found, I would use a number that is out of index inside the order list to indicate that this item should be at the bottom of the list.我解决这个问题的方法是在order列表中找到描述的索引,如果找不到,我会使用order列表中索引之外的数字来指示该项目应该在底部名单。

This would be my solution:这将是我的解决方案:

void testIt() {
  final outOfBounds = order.length + 1;
  const description = 'description';
  items.sort(
    (lhs, rhs) {
      final lhsDesc = (lhs[description] as String).toLowerCase();
      final rhsDesc = (rhs[description] as String).toLowerCase();
      final lhsIndex =
          order.contains(lhsDesc) ? order.indexOf(lhsDesc) : outOfBounds;
      final rhsIndex =
          order.contains(rhsDesc) ? order.indexOf(rhsDesc) : outOfBounds;
      return lhsIndex.compareTo(rhsIndex);
    },
  );
}

And the result is:结果是:

[{id: 1, id2: 3, description: Top European}, {id: 0, id2: 5, description: Top USA}, {id: 6, id2: 6, description: Top Rest of the world}, {id: 2, id2: 2, description: Top A}, {id: 3, id2: 0, description: Top Z}, {id: 4, id2: 4, description: Top C}, {id: 5, id2: 1, description: Top D}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM