4

I have a List with same objects.

And I would like two sort all of them by two properties

First name (from a to Z)

Second type (numbers by ascending, like 1,2,3...)

void main() {
  List<MyObject> list = List();
  list.add(MyObject('Apple', 'definition of type #1'));
  list.add(MyObject('Strawberry', 'definition of type #8'));
  list.add(MyObject('Banana', 'definition of type #2'));
  list.add(MyObject('Orange', 'definition of type #3'));
  list.add(MyObject('Kiwi', 'definition of type #1'));
  list.add(MyObject('Peach', 'definition of type #4'));
  list.add(MyObject('Orange', 'definition of type #1'));
  list.add(MyObject('Apple', 'definition of type #8'));
  list.add(MyObject('Peach', 'definition of type #2'));
  list.add(MyObject('Strawberry', 'definition of type #17'));
  list.add(MyObject('Peach', 'definition of type #1'));
  list.add(MyObject('Banana', 'definition of type #5'));
  list.add(MyObject('Apple', 'definition of type #16'));
  list.add(MyObject('Strawberry', 'definition of type #7'));

  for (MyObject _object in list) {
    print(_object.name + ' ' + _object.type);
  }

  RegExp regExp = new RegExp(
    r"#'?.*",
  );

  list.sort((a, b) {
    int _a = int.parse(regExp.stringMatch(a.type).replaceAll('#', ''));
    int _b = int.parse(regExp.stringMatch(b.type).replaceAll('#', ''));

    return _a
        .compareTo(_b); //to get the order other way just switch `adate & bdate`
  });

  list.sort((a, b) => a.name.compareTo(b.name));
}

class MyObject {
  String name;
  String type;

  MyObject(this.name, this.type);
}

I want output like this,

Apple #1
Apple #8
Apple #16
Banana #2
Banana #5
...

I tried to use a regex method for parsing numbers (from 'definition of type #(number)')

But If I sort list by this, I could not sort list from a to Z (name's)

alp_the_developer
  • 615
  • 1
  • 9
  • 23
  • Does this answer your question? [Sort a list of maps in Dart - Second Level Sort in Dart](https://stackoverflow.com/questions/22177838/sort-a-list-of-maps-in-dart-second-level-sort-in-dart) – Wiktor Stribiżew Apr 21 '20 at 12:45

4 Answers4

11

You just need to sort once and define the sorting method so it compares the type if name are the same:

void main() {
  List<MyObject> list = List();
  list.add(MyObject('Apple', 'definition of type #1'));
  list.add(MyObject('Strawberry', 'definition of type #8'));
  list.add(MyObject('Banana', 'definition of type #2'));
  list.add(MyObject('Orange', 'definition of type #3'));
  list.add(MyObject('Kiwi', 'definition of type #1'));
  list.add(MyObject('Peach', 'definition of type #4'));
  list.add(MyObject('Orange', 'definition of type #1'));
  list.add(MyObject('Apple', 'definition of type #8'));
  list.add(MyObject('Peach', 'definition of type #2'));
  list.add(MyObject('Strawberry', 'definition of type #17'));
  list.add(MyObject('Peach', 'definition of type #1'));
  list.add(MyObject('Banana', 'definition of type #5'));
  list.add(MyObject('Apple', 'definition of type #16'));
  list.add(MyObject('Strawberry', 'definition of type #7'));

  RegExp regExp = new RegExp(
    r"#'?.*",
  );

  list.sort((a, b) {
    int compare = a.name.compareTo(b.name);

    if (compare == 0) {
      int _a = int.parse(regExp.stringMatch(a.type).replaceAll('#', ''));
      int _b = int.parse(regExp.stringMatch(b.type).replaceAll('#', ''));

      return _a.compareTo(_b);
    } else {
      return compare;
    }
  });

  for (MyObject _object in list) {
    print(_object.name + ' ' + _object.type);
  }
}

class MyObject {
  String name;
  String type;

  MyObject(this.name, this.type);
}

Output:

Apple definition of type #1
Apple definition of type #8
Apple definition of type #16
Banana definition of type #2
Banana definition of type #5
Kiwi definition of type #1
Orange definition of type #1
Orange definition of type #3
Peach definition of type #1
Peach definition of type #2
Peach definition of type #4
Strawberry definition of type #7
Strawberry definition of type #8
Strawberry definition of type #17
julemand101
  • 28,470
  • 5
  • 52
  • 48
6

To do a complete comparison, you should implement Comparable< MyObject > which exposes a compareTo() method to sort by one ore more property.

See full example below :

void main() {
  List<MyObject> list = List();
  list.add(MyObject('Apple', 'definition of type #1'));
  list.add(MyObject('Strawberry', 'definition of type #8'));
  list.add(MyObject('Banana', 'definition of type #2'));
  list.add(MyObject('Orange', 'definition of type #3'));
  list.add(MyObject('Kiwi', 'definition of type #1'));
  list.add(MyObject('Peach', 'definition of type #4'));
  list.add(MyObject('Orange', 'definition of type #1'));
  list.add(MyObject('Apple', 'definition of type #8'));
  list.add(MyObject('Peach', 'definition of type #2'));
  list.add(MyObject('Strawberry', 'definition of type #17'));
  list.add(MyObject('Peach', 'definition of type #1'));
  list.add(MyObject('Banana', 'definition of type #5'));
  list.add(MyObject('Apple', 'definition of type #16'));
  list.add(MyObject('Strawberry', 'definition of type #7'));

  list.sort();
  for (MyObject _object in list) {
    print(_object);
  }
}

abstract class Comparable {
   int compareTo(Object obj){
   }
}

class MyObject implements Comparable<MyObject> {
  static final RegExp _regExp = RegExp(r'\D+');

  final String name;
  final String type;

  MyObject(this.name, this.type);

  @override
  int compareTo(MyObject other) {
    int result = name?.compareTo(other?.name) ?? 0;
    if (result == 0) {
      int type1 = int.tryParse(type?.replaceAll(_regExp, '') ?? 0);
      int type2 = int.tryParse(other?.type?.replaceAll(_regExp, '') ?? 0);
      result = type1.compareTo(type2);
    }
    return result;
  }

  @override
  String toString() => '$name $type';
}

it prints

Apple definition of type #1
Apple definition of type #8
Apple definition of type #16
Banana definition of type #2
Banana definition of type #5
Kiwi definition of type #1
Orange definition of type #1
Orange definition of type #3
Peach definition of type #1
Peach definition of type #2
Peach definition of type #4
Strawberry definition of type #7
Strawberry definition of type #8
Strawberry definition of type #17
Adrien Arcuri
  • 1,962
  • 1
  • 16
  • 30
4

Here is an example in Dart that sorts by sector then position.

static sortBySectorPosition(List<Subclass> subclasses) {
      subclasses.sort((a, b) {
        if (a.sector! == b.sector!) {
          return a.position!.compareTo(b.position!);
        } else {
          return a.sector!.compareTo(b.sector!);
        }
      });
}
MSaudi
  • 4,442
  • 2
  • 40
  • 65
1

The other answers are fine, but I'd recommend using the sorted package. It's pretty sure that it's the cleanest solution.

To make the example shorter, I'm going to assume that MyObject is the following class:

class MyObject {
  const MyObject(this.firstName, this.number);

  final String firstName;
  final int number;

  @override
  String toString() => '$firstName $number';
}

You can sort Iterable<Person> like this:

final list = [
  MyObject('Apple', 1),
  MyObject('Strawberry', 8),
  MyObject('Banana', 2),
  MyObject('Orange', 3),
  MyObject('Kiwi', 1),
  MyObject('Peach', 4),
];

final sortedList = list.sorted(
  [
    SortedComparable<MyObject, String>((person) => person.firstName),
    SortedComparable<MyObject, int>((person) => person.number),
  ],
);

print(sortedList);

Hope this helps!

Bartek Pacia
  • 1,085
  • 3
  • 15
  • 37