'Dart spread operator to say "place this in list if it's not null"

Is there a combination of Dart spread operators and null-aware operators that will do this?

[
  1, 
  ...twoOrNull() // this will be inserted only if it's null. something else than the ... operator will be here. 
  3, 
]

So the list will be either [1, 2, 3] or [1, 3]. I guess twoOrNull() can return [2] or [], but it would be nice if it could return 2 or null.

Is this possible without introducing a variable?



Solution 1:[1]

There is a null-aware spread operator (...?), but your twoOrNull() function would have to return either [2]or null; the spread operator expands an iterable within another collection literal, and it doesn't make sense to "spread" an int.

There's also Dart's collection-if construct, but it would require either calling twoOrNull() twice or saving the result in a variable:

[
  1, 
  if (twoOrNull() != null) twoOrNull(),
  3, 
]

See the Lists section from the Dart Language Tour for more information about spread and collection-if.

Solution 2:[2]

An one-liner without side effect:

[
  1,
  ...[twoOrNull()]..removeWhere((x) => x == null),
  3,
]

The idea here is to map from an int twoOrNull() to a list of either [2] or [], then use the spreading operator ... to unfold it.

Note that having one twoOrNull() in this case is fine, but as soon as you start having more elements that need null checking before being added to the list, readability will suffer. In that case, consider delaying the null check to after you have added the element to the list, i.e.

[
  1,
  twoOrNull(),
  3,
]..removeWhere((x) => x == null)

This will make the code a lot more straightforward and readable.

EDIT:

For the best readability in the list, it would be perfect to have a twoOrNullList() function returning either [2] or []. Then you can use it pretty much similar to what you proposed:

var twoOrNullList() => [twoOrNull()]..removeWhere((x) => x == null)
[
  1,
  ...twoOrNullList(),
  3,
]

Solution 3:[3]

Yet another solution.

Iterable<T> emit<T>(T? p) sync* {
  if (p != null) {
    yield p;
  }
}

[
  1,
  ...emit(twoOrNull()),
  3,
]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jamesdlin
Solution 2
Solution 3 PeterM