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

时间:2018-11-29 21:39:44

标签: dart flutter

有什么想法如何按对象属性之一的字母顺序对对象列表进行排序(不是名称而是属性所拥有的实际值)?

谢谢!

11 个答案:

答案 0 :(得分:14)

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

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

答案 1 :(得分:8)

这是我对这个好问题的贡献。如果某人难以理解@Nate Bosch答案的工作方式,并且您想对自定义模型类列表进行排序,则可以采用这种方式。

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

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。现在,您可以在compareTo方法内调用sort方法。

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

答案 2 :(得分:6)

不可变扩展名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);

答案 3 :(得分:5)

通常,您可以为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();

按多个属性排序(也称为子分类)

如果要按多个属性排序,通常的方法是对每个属性按重要性相反的顺序执行 stable 排序。例如,如果要主要按姓氏对名称进行排序,然后按给定名称对姓氏进行子排序,则首先要按给定名称进行排序,然后再按姓氏执行稳定的排序。有关如何执行稳定排序的信息,请参见下文。

或者,您可以使用考虑多个属性的比较功能进行排序。例如:

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()很昂贵,这特别浪费。在这种情况下,Schwartzian transform可能会更快(以使用更多内存为代价)。此方法将您的对象映射到可直接排序的键,对键进行排序,然后提取原始对象。 (这就是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);
}

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

答案 4 :(得分:5)

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

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

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

users = users.reversed.toList();

答案 5 :(得分:2)

类似于@ pavel-shorokhovs的答案,但类型强:

    var table = $("<table/>");
    $.each(data, function(rowIndex, r) {
        var row = $("<tr/>");
        $.each(r, function(colIndex, c) {           
            var cellMarkup = "<t"+(rowIndex == 0 ?  "h" : "d")+"/>";
            var cell = $(cellMarkup);
            cell.text(c);
            if(colIndex == 5){   --> I am doing this to flag an error in red. Nothing related to the posed question.
                if( $.trim(c.toLowerCase() ) === "error" ){
                    cell.addClass("error blink");
                }
        }  

            row.append(cell);               
        });
        table.append(row);                              
    });

    return container.html(table);


} 

答案 6 :(得分:2)

在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 }]

答案 7 :(得分:1)

如果要按属性“名称”对对象“对象”进行排序,请执行以下操作

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

答案 8 :(得分:1)

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


  }

答案 9 :(得分:1)

反序排序:

list.sort((a, b) {
          return b.status.toLowerCase().compareTo(a.status.toLowerCase());
        });

答案 10 :(得分:0)

使用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]