6

I can sort a list like this in Dart:

final myList = [6, 3, 7, 1, 0, 2];
myList.sort();

However, this is a destructive sort since it mutates it in place. I'd like to do something like this:

final myList = [6, 3, 7, 1, 0, 2];
final newList = myList.sorted();

where my list stays the same but newList contains the sorted list. Dart apparently doesn't have this functionality, so how do I implement that myself?

In searching for the answer to this question my main struggle was knowing the proper way to copy a list, which wasn't as obvious as it seems like it should be. I found the answer to that, so I am also posting an answer to my original question below, Q&A style.

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393

3 Answers3

4

You can create a new sorted list without affecting the original list like so:

final myList = [6, 3, 7, 1, 0, 2];
final sorted = myList.toList()..sort();

Calling toList() copies the list. The .. is to get a reference to the list itself since sort() is a void function. This gives the same result:

final sorted = myList.toList();
sorted.sort();

Printing the values of both lists gives the following results:

print(myList); // [6, 3, 7, 1, 0, 2]
print(sorted); // [0, 1, 2, 3, 6, 7]

You can read more about copying lists here.

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
1

I'd suggest you to create a fixed-length list.

final myList = [6, 3, 7, 1, 0, 2];
final sortedList = myList.toList(growable: false)..sort();
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
0

It seems to me that this question is really "How can I copy a List?", and the sorting aspect is tangential.

There are multiple ways to copy an Iterable to a new List:

  • Using a method on the original Iterable: iterable.toList()
  • Using a List constructor: List.of(iterable)
  • Using the spread operator in a List literal: [...iterable]. Note that this always creates a growable List.

Note that List.from should not be used since that uses dynamic types and loses type information. Effective Dart prefers .toList().

Also note that the above applies to Sets too (iterable.toSet(), {...iterable}, Set.of(iterable)).

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • My understanding is that `List.of` isn't useful for anything (since `toList` can also specify non-growable). `List.from` is useful for downcasting but the type should be specified. See this: https://stackoverflow.com/questions/61536959/in-dart-which-is-better-list-generate-or-list-of-or-list-from/61541310#61541310 – Suragch Aug 27 '21 at 07:48
  • @Suragch Right, `List.of` isn't any better than `.toList()`. I *do* contend that `List.of` can be more readable than `.toList`; it's more obvious that `List.of` creates a copy, and the code might want to emphasize that. – jamesdlin Aug 27 '21 at 08:08
  • I also didn't mean to imply that `List.of` should necessarily be the preferred approach, only that `List.from` should be avoided. I'll adjust the wording. – jamesdlin Aug 27 '21 at 08:31
  • I agree with you that `List.of` is more readable than `toList`. It seems very strange indeed to call `toList` when you already have a list. I will say, though, that the mere existence of `List.from` blurred the meaning of `List.of` quite a bit for me at first. – Suragch Aug 27 '21 at 10:04
  • @jamesdlin As`List.of` is more readable than `.toList()`, I think Dart team should change `List.of` implementation to actually return `.toList()` because the current implementation of `List.of` seems to carry no meaning. – CopsOnRoad Aug 28 '21 at 12:42