How to properly sort list by another list in Dart
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.
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}]
Philipos D.
“The best programs are written so that computing machines can perform them quickly and so that human beings can understand them clearly. A programmer is ideally an essayist who works with traditional aesthetic and literary forms as well as mathematical concepts, to communicate the way that an algorithm works and to convince a reader that the results will be correct.” ― Donald E. Knuth, Selected Papers on Computer Science
Updated on December 19, 2022Comments
-
Philipos D. 11 months
I have two lists, 1 is a list of Map items, and another list which is the order.
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.