sortBy

Ordena de forma ascendente por una clave que extraes, en lugar de escribir un comparador a mano.

List<A> sortBy<A>(Object? Function(A a) f, Iterable<A> iterable) Future<List<A>> sortByAsync<A>(Object? Function(A a) f, FxAsyncIterable<A> iterable) Fx<T> Fx.sortBy(Object? Function(T a) f) // chain (sync) — still lazy, call .toList() Future<List<T>> FxAsync.sortBy(Object? Function(T a) f) // chain (async) — already a terminal

Lección

sortBy es el hermano cómodo de sort: en lugar de escribir tú (a, b) => a.age.compareTo(b.age), le das a sortBy un extractor de clave — (a) => a['age'] — y ordena por las claves extraídas, siempre de forma ascendente, comparándolas siempre con Comparable.compare.

Por debajo no es sort((a, b) => compare(f(a), f(b))), y la diferencia se nota en tu callback: esa forma llamaría a f dos veces por comparación, unas 2·n·log n veces. sortBy extrae cada clave exactamente una vez y después ordena por las claves extraídas, así que un extractor costoso cuesta n llamadas, no 2·n·log n. Aun así, mantén f pura y barata: el número de llamadas está garantizado, el orden en que ocurren no.

Todas las garantías de sort se mantienen sin cambios: el resultado siempre es una lista nueva, nunca una mutación de la entrada. Y el mismo matiz de la forma de cadena también se aplica: en la cadena síncrona Fx, .sortBy(f) devuelve otro Fx<T>, así que sigues necesitando .toList() para materializarlo, mientras que en la cadena FxAsync, .sortBy(f) ya es un terminal que devuelve Future<List<T>>.

Si necesitas orden descendente, o una ordenación por varias claves, vuelve a sort con un comparador explícito — sortBy solo cubre el caso habitual de «ascendente por una clave extraída».

Demo 1 · Fundamentos

Demo 2 · Asíncrono — ya es un terminal

Pruébalo tú

Ejercicio: ordena a las personas por edad, de menor a mayor.

Relacionado: sort — la forma basada en comparador sobre la que se construye · min · max — para un solo extremo en lugar de una ordenación completa · pluck — extrae la misma clave sin ordenar