Dart collections with DartX extensions

Read in Ukrainian

Dart’s Iterable and List offer a basic set of methods to modify and query collections. However, coming from the C# background, which has a marvelous LINQ-to-Objects library, I felt that a part of the functionality that I was using on a daily basis is missing. Of course, any task can be solved with the dart.core methods only, but it sometimes requires multi-line solutions, and the code is not so obvious and takes effort to understand. We all know that developers spend a lot of time reading the code, and it is crucial to have it concise and obvious.

dartx package allows developers to use elegant and readable single-line operations on collections (and other Dart types).

Below we’ll compare how these tasks are solved with plain Dart vs. dartx:

  • first / last collection item or null / default value / by condition;
  • map / filter / iterate collection items depending on their index;
  • converting a collection to a map;
  • sorting collections;
  • collecting unique items;
  • min / max / average by items property;
  • filtering out null items;

and look at some additional useful extensions.

All examples require dartx dependency in pubspec.yaml file and

First / last collection item…

… or null

To get the first and last collection items in plain Dart one would write:

which throws a StateError if list is empty. Or explicitly return null:

Using dartx allows:

Similarly:

returns null if the index is out of bounds of the list.

… or default value

Given you now remember that .first and .last getters throw errors when list is empty, to get the first and last collections items or default value, in plain Dart you’d write:

Using dartx:

Similar to elementAtOrNull:

returns defaultValue if the index is out of bounds of the list.

… by condition

To get the first and last collection items that match some condition or null, a plain Dart implementation would be:

which will throw StateError for empty list unless orElse is provided:

dartx shortens the implementation to:

… collection items depending on their index

Map…

It’s not a rare case when you need to obtain a new collection where each item somehow depends on its index. For example, each new item is a string representation of an item from the original collection + its index.

If you like me prefer one-liners, in plain Dart it would be:

With dartx it’s much simpler:

I applied .toList() because this and most other extension methods return lazy Iterable.

Filter…

For another example, let’s say there is a need to collect only odd-indexed items. With plain Dart, this can be implemented like:

Or in one line:

With dartx it’s only:

Iterate…

How would you log collection content specifying item indexes?

In plain Dart:

With dartx:

Converting a collection to a map

For example, there is a need to convert a list of distinct Person objects to a Map<String, Person> where keys are person.id, and values are whole person instances.

In plain Dart:

With dartx:

To get a map where keys are DateTime and values are List<Person> of people who were born that day, in plain Dart you’d write:

It’s much simpler with dartx:

Sorting collections

How would you sort a collection in plain Dart? You have to keep in mind that

modifies the source collection, and to get a new instance you’d have to write:

dartx provides an extension to get a new List instance:

And how would you sort collection items based on some property?

Plain Dart:

With dartx:

To go even further, you can sort collection items by multiple properties:

Collecting unique items

To get distinct collection items one might use this plain Dart implementation:

which does not guarantee to preserve items order or come up with a multi-line solution.

With dartx, it’s as easy as:

Min / max / average by item property

To find a min / max collection item, we could for example sort it and take first / last item:

The same approach can be applied to sort by items’ property:

or:

But with dartx it’s much easier:

which by the way will return null for empty collections.

And if collection items implement Comparable, methods without selectors can be applied:

You can also easily obtain the average:

and the sum of num collections or num items properties:

Filtering out null items

With plain Dart:

With dartx:

More useful extensions

There are other useful extensions in dartx. We won’t go into deeper details here, but I hope the naming and the code are self-explanatory.

joinToString

all (every) / none

first / second / third / fourth collection items

takeFirst / takeLast

firstWhile / lastWhile

Final words

The dartx package contains many more extensions for Iterable, List, and other Dart types. The best way to explore its capabilities is by browsing the source code.

If you, as me, find the package useful, remember to give it 👍🏻 on pub.dev and ⭐️ on GitHub.

Thanks to package authors Simon Leier and Pascal Welsch.

Follow Flutter Community on Twitter: https://www.twitter.com/FlutterComm

--

--

Anna Leushchenko 👩‍💻💙📱🇺🇦
Flutter Community

Google Developer Expert in Dart and Flutter | Author, speaker at tech events, mentor, OSS contributor | Passionate mobile apps creator