按属性值对 Flutter (Dart)中的对象列表进行排序

如何根据对象列表中某个属性的字母顺序(不是名称,而是该属性所包含的实际值)对对象列表进行排序?

166382 次浏览

如果你想按属性“ name”对对象“ object”进行排序,可以这样做

objects.sort((a, b) {
return a.value['name'].toString().toLowerCase().compareTo(b.value['name'].toString().toLowerCase());
});

可以将比较函数传递给 List.sort

someObjects.sort((a, b) => a.someProperty.compareTo(b.someProperty));

我有 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);
}




}

这是我对这个好问题的贡献。如果有人很难理解@Nate Bosch 的答案是如何工作的,并且你想对你的自定义模型类列表进行排序,那么你可以这样做。

1. 必须在模型类中实现 Comparable抽象类。 它有一个方法 compareTo,您必须重写它。 例如,我有这个 StudentMarks模型类,其中包含 mark 属性。

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;
}
}

2. 现在可以在 sort方法中调用 compareTo方法。

void _sortStudents({bool reversed: false}) {
_students.sort((a, b) {
return a.compareTo(b);
});


if (reversed) {
_students = _students.reversed.toList();
}


setState(() {});
}

参考这个链接,你想知道更多关于 Comparable类的信息

Https://api.dart.dev/stable/2.1.0/dart-core/comparable-class.html

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);

通常,您可以为 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提供稳定的 insertionSortmergeSort实现。


但比较可能代价高昂

假设您有一个自定义的比较函数,它看起来类似于:

int compareMyCustomClass(MyCustomClass a, MyCustomClass b) {
var a0 = computeValue(a);
var b0 = computeValue(b);
return a0.compareTo(b0);
}

排序可能会多次调用每个元素上的 computeValue(),如果 computeValue()代价高昂,这种做法尤其浪费。在这种情况下,施瓦兹变换可以更快(代价是使用更多的内存)。这种方法将对象映射到可直接排序的键,对键进行排序,并提取原始对象。(这就是 Python 的 sortsorted函数的工作方式。)

这里有一个可能的实现方法:

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);
}

使用 Comparator函数,按 idUsers进行排序。

Comparator<UserModel> sortById = (a, b) => a.id.compareTo(b.id);
users.sort(sortById);

现在我们可以按照倒序/降序对它进行排序。

users = users.reversed.toList();

类似于@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());
});

这对我很有效:

myList..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));

更重要的是,你可以使用 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);
});
}

步骤1: 向类中添加 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;
}
}
}

第二步: 整理你的清单:

  • 提升:

    Sort (((a,b){ 返回 a.compareTo (b) ; });

  • 通过降序:

    Sort (((a,b){ 返回 b.compareTo (a) ; });