[英]Sort a list of different objects with the same property (timestamp) in Flutter/Dart
[英]Sort a list of objects in Flutter (Dart) by property value
如何按其屬性之一的字母順序對對象列表進行排序(不是名稱,而是屬性所持有的實際值)?
您可以將比較函數傳遞給List.sort
。
someObjects.sort((a, b) => a.someProperty.compareTo(b.someProperty));
如果要按屬性“名稱”對對象“對象”進行排序,請執行以下操作
objects.sort((a, b) {
return a.value['name'].toString().toLowerCase().compareTo(b.value['name'].toString().toLowerCase());
});
通常,您可以為List.sort
提供自定義比較功能。
/// Desired relation | Result
/// -------------------------------------------
/// a < b | Returns a negative value.
/// a == b | Returns 0.
/// a > b | Returns a positive value.
///
int mySortComparison(SomeClass a, SomeClass b) {
final propertyA = someProperty(a);
final propertyB = someProperty(b);
if (propertyA < propertyB) {
return -1;
} else if (propertyA > propertyB) {
return 1;
} else {
return 0;
}
}
list.sort(mySortComparison);
如果您正在對您擁有的一些自定義類進行排序,您也可以讓您的類實現Comparable
接口:
class MyCustomClass implements Comparable<MyCustomClass> {
...
@override
int compareTo(MyCustomClass other) {
if (someProperty < other.someProperty) {
return -1;
} else if (someProperty > other.someProperty) {
return 1;
} else {
return 0;
}
}
}
然后您可以直接使用list.sort()
而不提供回調。
請注意,如果您按已實現Comparable
接口的單個屬性進行排序,則實現比較函數要簡單得多。 例如:
class MyCustomClass implements Comparable<MyCustomClass> {
...
@override
int compareTo(MyCustomClass other) =>
someProperty.compareTo(other.someProperty);
}
如果要反轉排序順序,可以使比較函數返回一個帶有相反符號的值。 或者,只需在排序后顯式反轉列表:
list = (list..sort()).reversed.toList();
如果要按多個屬性排序,一般的方法是按重要性相反的順序對每個屬性執行穩定排序。 例如,如果您想主要按姓氏對姓名進行排序,然后按名字在姓氏中進行子排序,那么您將首先按名字排序,然后按姓氏執行穩定的排序。 請參閱下文了解如何執行穩定排序。
或者,您可以使用包含多個屬性的比較函數進行排序。 例如:
class Name {
Name({String surname, String givenName})
: surname = surname ?? "",
givenName = givenName ?? "";
final String surname;
final String givenName;
}
int compareNames(Name name1, Name name2) {
var comparisonResult = name1.surname.compareTo(name2.surname);
if (comparisonResult != 0) {
return comparisonResult;
}
// Surnames are the same, so subsort by given name.
return name1.givenName.compareTo(name2.givenName);
}
List.sort
不保證是穩定的排序。 如果您需要穩定的排序, package:collection
提供了穩定的insertionSort
排序和mergeSort
排序實現。
假設您有一個看起來像這樣的自定義比較函數:
int compareMyCustomClass(MyCustomClass a, MyCustomClass b) {
var a0 = computeValue(a);
var b0 = computeValue(b);
return a0.compareTo(b0);
}
排序可能會在每個元素上多次調用computeValue()
,如果computeValue()
很昂貴,這尤其浪費。 在這種情況下, Schwartzian 變換可能會更快(以使用更多內存為代價)。 這種方法將您的對象映射到可直接排序的鍵、對鍵進行排序並提取原始對象。 (這就是 Python 的sort
和sorted
函數的工作原理。)
這是一種可能的實現:
class _SortableKeyPair<T, K extends Comparable<Object>>
implements Comparable<_SortableKeyPair<T, K>> {
_SortableKeyPair(this.original, this.key);
final T original;
final K key;
@override
int compareTo(_SortableKeyPair<T, K> other) => key.compareTo(other.key);
}
// Returns a sorted *copy* of [items] according to the computed sort key.
List<E> sortedWithKey<E, K extends Comparable<Object>>(
Iterable<E> items,
K Function(E) toKey,
) {
final keyPairs = [
for (var element in items) _SortableKeyPair(element, toKey(element)),
]..sort();
return [
for (var keyPair in keyPairs) keyPair.original,
];
}
void main() {
final list = <MyCustomClass>[ ... ];
final sorted = sortedWithKeys(list, computeValue);
}
List 的不可變擴展sortedBy
。
extension MyIterable<E> on Iterable<E> {
Iterable<E> sortedBy(Comparable key(E e)) =>
toList()..sort((a, b) => key(a).compareTo(key(b)));
}
並使用
list.sortedBy((it) => it.name);
這是我對這個好問題的貢獻。 如果有人難以理解@Nate Bosch 的答案是如何工作的,並且您想對自定義模型類列表進行排序,那么您可以這樣做。
1. 你必須在你的模型類中實現
Comparable<\/code>抽象類。<\/strong>
它具有您必須覆蓋的方法
compareTo<\/code> 。
例如,我有這個
StudentMarks<\/code>模型類,其中包含標記屬性。
class StudentMarks implements Comparable {
int marks;
StudentMarks({
this.marks,
});
@override
int compareTo(other) {
if (this.marks == null || other == null) {
return null;
}
if (this.marks < other.marks) {
return 1;
}
if (this.marks > other.marks) {
return -1;
}
if (this.marks == other.marks) {
return 0;
}
return null;
}
}
在 Dart/Flutter 中對對象列表進行排序
1使用自定義比較功能:
class Customer {
String name;
int age;
Customer(this.name, this.age);
@override
String toString() {
return '{ ${this.name}, ${this.age} }';
}
}
main() {
List customers = [];
customers.add(Customer('Jack', 23));
customers.add(Customer('Adam', 27));
customers.add(Customer('Katherin', 25));
customers.sort((a, b) => a.age.compareTo(b.age));
print('Sort by Age: ' + customers.toString());
customers.sort((a, b) => a.name.compareTo(b.name));
print('Sort by Name: ' + customers.toString());
}
輸出:
Sort by Age: [{ Jack, 23 }, { Katherin, 25 }, { Adam, 27 }]
Sort by Name: [{ Adam, 27 }, { Jack, 23 }, { Katherin, 25 }]
2第二種方法是擴展Comparable
抽象類並覆蓋compareTo()
方法。 現在我們不需要傳遞比較函數,我們只需調用list.sort()
而不是list.sort(compare)
。
class Customer extends Comparable {
String name;
int age;
Customer(this.name, this.age);
@override
String toString() {
return '{ ${this.name}, ${this.age} }';
}
// sort by Name (asc), then age (desc)
@override
int compareTo(other) {
int nameComp = this.name.compareTo(other.name);
if (nameComp == 0) {
return -this.age.compareTo(other.age); // '-' for descending
}
return nameComp;
}
}
main() {
List customers = [];
customers.add(Customer('Jack', 23));
customers.add(Customer('Adam', 27));
customers.add(Customer('Katherin', 25));
customers.add(Customer('Jack', 32));
customers.sort();
print(customers);
}
輸出:
[{ Adam, 27 }, { Jack, 32 }, { Jack, 23 }, { Katherin, 25 }]
使用
Comparator<\/code>函數,按
id<\/code>對
Users<\/code>進行排序。
Comparator<UserModel> sortById = (a, b) => a.id.compareTo(b.id);
users.sort(sortById);
更重要的是,您可以使用Comparable.compare
更清楚,例如:
class _Person {
final int age;
final String name;
_Person({required this.age, required this.name});
}
void _test() {
final array = [
_Person(age: 10, name: 'Dean'),
_Person(age: 20, name: 'Jack'),
_Person(age: 30, name: 'Ben'),
];
// ascend with age
// Dean Jack Ben
array.sort((p1, p2) {
return Comparable.compare(p1.age, p2.age);
});
// decend with age
// Ben Jack Dean
array.sort((p1, p2) {
return Comparable.compare(p2.age, p1.age);
});
// ascend with name
// Ben Dean Jack
array.sort((p1, p2) {
return Comparable.compare(p1.name, p2.name);
});
}
類似於@pavel-shorokhovs 答案,但強類型:
extension IterableExtensions<T> on Iterable<T> {
Iterable<T> sortBy<TSelected extends Comparable<TSelected>>(
TSelected Function(T) selector) =>
toList()..sort((a, b) => selector(a).compareTo(selector(b)));
Iterable<T> sortByDescending<TSelected extends Comparable<TSelected>>(
TSelected Function(T) selector) =>
sortBy(selector).toList().reversed;
}
要以相反的順序對其進行排序:
list.sort((a, b) {
return b.status.toLowerCase().compareTo(a.status.toLowerCase());
});
我有 fpgrowth 機器學習輸出\/結果,列表的每個元素都包含另一個列表和頻率字段,我將按頻率降序排序,所以我使用了一些遞歸來嘗試它可能有效我知道我遲到了,但我正在發布也許其他人可以受益。
sort(List<FrequentItem> fqItems) {
int len = fqItems.length;
if(len==2){
if(fqItems[0].frequency>fqItems[1].frequency){
sortedItems.add(fqItems[0]);
sortedItems.add(fqItems[1]);
}else{
sortedItems.add(fqItems[1]);
sortedItems.add(fqItems[0]);
}
return;
}else{
FrequentItem max = fqItems[0];
int index =0;
for(int i=0;i<len-2;i++){
if(max.frequency<fqItems[i+1].frequency){
max = fqItems[i+1];
index = i+1;
}
}
sortedItems.add(max);
fqItems.removeAt(index);
sort(fqItems);
}
}
第一步:給class添加compareTo方法:
class Student {
String? name;
int? age;
Student({this.name, this.age});
int getAge() {
if (age == null) return 0;
return age!;
}
@override
int compareTo(Student other) {
var a = getAge();
var b = other.getAge();
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
}
第 2 步:對列表進行排序:
通過升序:
studentList.sort((a, b) { return a.compareTo(b); });
通過降序:
studentList.sort((a, b) { return b.compareTo(a); });
使用Dart靜態擴展方法對列表進行排序的示例:
import 'package:enumerable/enumerable.dart';
void main(List<String> args) {
var strings = ["c", "bb", "b", "a", "cc", null, "aaa", 'ccc'];
var query = strings.orderByDescending((s) => s?.length ?? 0).thenBy((s) => s);
print(query.toList());
}
結果:
[aaa, ccc, bb, cc, a, b, c, null]
按多個屬性排序的示例(雙重排序)。
import 'package:enumerable/enumerable.dart';
void main(List<String> args) {
final persons = [
Person("Peter", 25),
Person("Peter", 22),
Person("John", 26),
Person("Max", 26)
];
final query = persons.orderBy((p) => p.name).thenBy((p) => p.age);
print(query.toList());
}
class Person {
String name;
int age;
Person(this.name, this.age);
String toString() => '$name $age';
}
結果:
[John 26, Max 26, Peter 22, Peter 25]
它對我有用:
myList..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.