| |

Dart 15 ๐ŸŽฏ Collection if and Collection for Literals

Dart’s collection literals โ€” lists, sets, and maps โ€” support if and for inside the brackets. This is not a generic language feature; it is a special syntax that the collection literal grammar allows. A collection-if includes an element only when a condition is true. A collection-for includes multiple elements generated by an iteration. Both are expressions inside the literal, and they compose with each other and with the spread operator to build collections declaratively.

The result is that many collection-building patterns that would otherwise require imperative add calls become single expressions. A list that conditionally includes an item, a set built from a filtered range, a map assembled from a list of entries โ€” each is a literal with embedded control flow. The code reads as a description of the collection’s contents rather than as a sequence of mutations.

This chapter covers the syntax and semantics of collection-if and collection-for in lists, sets, and maps, the interaction with spread operators, the conditions under which they are appropriate, and the patterns that make collection construction declarative.

Key point: Collection-if (if (cond) element) includes an element conditionally. Collection-for (for (var x in items) element) includes multiple elements from an iteration. Both work inside list, set, and map literals, and both can be nested or combined with spread. They are expressions, not statements, and produce collection elements rather than executing a block.


Why collection-if and collection-for exist

The conditional-element problem. A list sometimes needs an element only when a condition is true. Without collection-if, this requires building the list with add calls, or creating it fully and then filtering, or using a ternary that produces a sentinel value. Collection-if puts the condition directly in the literal.

The mapped-collection problem. A list often needs to be built from another collection by transforming each element. Without collection-for, this requires a loop with add, or a map call with toList(). Collection-for expresses the iteration inside the literal.

The declarative problem. A literal that contains its own conditions and iterations describes what the collection should contain. An imperative sequence describes how to build it. When the collection is a fixed expression rather than a runtime computation, the declarative form is clearer.

The composition problem. Collection-if, collection-for, and spread compose. A list can conditionally include a spread, iterate over a range, and include literal elements, all in one expression. This makes complex collections expressible without intermediate variables.

The nested-collection problem. A list of lists, a set of maps, a map of lists โ€” nested collections are common. Collection-for flattens the construction, so a nested structure is built from a single literal rather than nested loops.


a. Collection-if in lists

A collection-if inside a list literal includes an element only when the condition is true.

var includeHeader = true;

var items = [
  if (includeHeader) 'Header',
  'Item 1',
  'Item 2',
];
print(items);  // [Header, Item 1, Item 2]

When the condition is false, the element is omitted, and the list contains the remaining elements.

var includeHeader = false;
var items = [
  if (includeHeader) 'Header',
  'Item 1',
];
print(items);  // [Item 1]

A collection-if can have an else clause, which includes one element or another:

var isLoggedIn = true;

var menu = [
  if (isLoggedIn) 'Logout' else 'Login',
  'Help',
];
print(menu);  // [Logout, Help]

The else branch is a single element, not a block. A ternary could also produce this, but the collection-if is more readable when the condition is about inclusion rather than selection.

Collection-if works in set literals as well:

var includeAdmin = false;
var roles = {
  'user',
  if (includeAdmin) 'admin',
};
print(roles);  // {user}

b. Collection-for in lists

A collection-for inside a list literal includes multiple elements generated by an iteration. The syntax mirrors a for statement but produces elements instead of executing a body.

var numbers = [1, 2, 3];

var doubled = [
  for (var n in numbers) n * 2,
];
print(doubled);  // [2, 4, 6]

The expression after the for clause is evaluated for each iteration, and its value is included in the collection. The loop variable is scoped to the expression.

A collection-for can iterate over a range:

var squares = [
  for (var i = 1; i <= 5; i++) i * i,
];
print(squares);  // [1, 4, 9, 16, 25]

It can iterate over a map’s entries:

var scores = {'Alice': 95, 'Bob': 87};

var labels = [
  for (var entry in scores.entries) '${entry.key}: ${entry.value}',
];
print(labels);  // [Alice: 95, Bob: 87]

The for clause in a collection literal supports the same forms as a for statement: for (var i = ...; ...; ...) and for (var x in iterable). It does not support break or continue, because it is an expression rather than a statement.


c. Collection-if and collection-for in maps

Maps support both constructs, with the key and value pair as the element.

var includeAge = true;

var user = {
  'name': 'Alice',
  if (includeAge) 'age': 30,
};
print(user);  // {name: Alice, age: 30}

The collection-if includes the key-value pair only when the condition is true.

Collection-for generates entries from an iteration:

var names = ['Alice', 'Bob', 'Carol'];

var nameLengths = {
  for (var name in names) name: name.length,
};
print(nameLengths);  // {Alice: 5, Bob: 3, Carol: 5}

The key expression and the value expression are both evaluated for each iteration, and the resulting entry is included in the map.

An else branch on a map’s collection-if provides an alternative entry:

var hasNickname = false;

var profile = {
  'name': 'Alice',
  if (hasNickname) 'nickname': 'Ali' else 'fullName': 'Alice Smith',
};
print(profile);  // {name: Alice, fullName: Alice Smith}

d. Combining collection-if, collection-for, and spread

The three constructs compose in a single literal.

var verbose = true;
var extras = ['--color', '--progress'];

var args = [
  'build',
  if (verbose) '--verbose',
  ...extras,
  for (var i = 0; i < 2; i++) '--level=$i',
  'target',
];
print(args);
// [build, --verbose, --color, --progress, --level=0, --level=1, target]

The literal includes a fixed element, a conditional element, a spread of a list, a generated sequence, and another fixed element. It is a single expression that builds the complete argument list.

A common pattern is filtering with a condition inside the collection-for:

var numbers = [1, 2, 3, 4, 5, 6];

var evens = [
  for (var n in numbers)
    if (n % 2 == 0) n,
];
print(evens);  // [2, 4, 6]

The collection-if inside the collection-for filters the generated elements. This is the declarative equivalent of a loop with a condition.

Nesting collection-for flattens nested structures:

var matrix = [
  [1, 2],
  [3, 4],
];

var flat = [
  for (var row in matrix)
    for (var cell in row) cell,
];
print(flat);  // [1, 2, 3, 4]

The outer loop iterates over rows, the inner loop iterates over cells, and the result is a flat list. This is equivalent to a nested loop with add calls but expressed as a literal.


e. Interaction with spread operators

Spread and collection-for both add multiple elements to a literal, but they differ in source. Spread expands an existing iterable; collection-for generates elements from an iteration.

var existing = [3, 4];

var combined = [
  1,
  2,
  ...existing,
  for (var i = 5; i <= 7; i++) i,
];
print(combined);  // [1, 2, 3, 4, 5, 6, 7]

Collection-for can generate iterables that are then spread:

var pairs = [
  [1, 2],
  [3, 4],
];

var flat = [
  for (var pair in pairs) ...pair,
];
print(flat);  // [1, 2, 3, 4]

The ...pair spreads each inner list into the result, which is the same as iterating the inner list. Both forms work; the spread form is often more concise when the inner collection is already a list.

Null-aware spread composes with collection-for as well:

List<int>? optional;

var result = [
  for (var i = 0; i < 3; i++) i,
  ...?optional,
];
print(result);  // [0, 1, 2]

Complete Example Session

// ============================================
// PART 1: COLLECTION-IF IN A LIST
// ============================================
void main() {
  var includeHeader = true;

  var items = [
    if (includeHeader) 'Header',
    'Item 1',
    'Item 2',
  ];

  print(items);  // [Header, Item 1, Item 2]
}
// ============================================
// PART 2: COLLECTION-IF WITH ELSE
// ============================================
void main() {
  var isLoggedIn = true;

  var menu = [
    if (isLoggedIn) 'Logout' else 'Login',
    'Help',
  ];

  print(menu);  // [Logout, Help]
}
// ============================================
// PART 3: COLLECTION-FOR IN A LIST
// ============================================
void main() {
  var numbers = [1, 2, 3];

  var doubled = [
    for (var n in numbers) n * 2,
  ];

  print(doubled);  // [2, 4, 6]
}
// ============================================
// PART 4: COLLECTION-FOR WITH A RANGE
// ============================================
void main() {
  var squares = [
    for (var i = 1; i <= 5; i++) i * i,
  ];

  print(squares);  // [1, 4, 9, 16, 25]
}
// ============================================
// PART 5: COLLECTION-IF IN A SET
// ============================================
void main() {
  var includeAdmin = false;

  var roles = {
    'user',
    if (includeAdmin) 'admin',
  };

  print(roles);  // {user}
}
// ============================================
// PART 6: COLLECTION-IF IN A MAP
// ============================================
void main() {
  var includeAge = true;

  var user = {
    'name': 'Alice',
    if (includeAge) 'age': 30,
  };

  print(user);  // {name: Alice, age: 30}
}
// ============================================
// PART 7: COLLECTION-FOR IN A MAP
// ============================================
void main() {
  var names = ['Alice', 'Bob', 'Carol'];

  var nameLengths = {
    for (var name in names) name: name.length,
  };

  print(nameLengths);  // {Alice: 5, Bob: 3, Carol: 5}
}
// ============================================
// PART 8: FILTER WITH COLLECTION-IF INSIDE FOR
// ============================================
void main() {
  var numbers = [1, 2, 3, 4, 5, 6];

  var evens = [
    for (var n in numbers)
      if (n % 2 == 0) n,
  ];

  print(evens);  // [2, 4, 6]
}
// ============================================
// PART 9: NESTED COLLECTION-FOR
// ============================================
void main() {
  var matrix = [
    [1, 2],
    [3, 4],
  ];

  var flat = [
    for (var row in matrix)
      for (var cell in row) cell,
  ];

  print(flat);  // [1, 2, 3, 4]
}
// ============================================
// PART 10: COMBINING ALL THREE
// ============================================
void main() {
  var verbose = true;
  var extras = ['--color', '--progress'];

  var args = [
    'build',
    if (verbose) '--verbose',
    ...extras,
    for (var i = 0; i < 2; i++) '--level=$i',
    'target',
  ];

  print(args);
  // [build, --verbose, --color, --progress, --level=0, --level=1, target]
}

These ten parts cover collection-if in lists, collection-if with else, collection-for in lists, collection-for with a range, collection-if in sets, collection-if in maps, collection-for in maps, filtering with a nested collection-if, nested collection-for, and combining all three constructs.


Quick Reference

Collection-If

FormExample
List[if (cond) element]
List with else[if (cond) a else b]
Set{if (cond) element}
Map{if (cond) key: value}
Map with else{if (cond) k1: v1 else k2: v2}

Collection-For

FormExample
In list[for (var x in items) x]
In set{for (var x in items) x}
In map{for (var x in items) x: f(x)}
Range[for (var i = 0; i < n; i++) i]
Over entries[for (var e in map.entries) e.key]

Combining Constructs

CombinationExample
If inside for[for (var n in list) if (n > 0) n]
For with spread[for (var row in matrix) ...row]
If with spread[if (cond) ...items]
All three[if (c) x, ...items, for (...) y]

Comparison with Imperative

DeclarativeImperative
[if (c) x]if (c) list.add(x);
[for (n in items) f(n)]for (n in items) list.add(f(n));
[for (r in matrix) ...r]for (r in matrix) list.addAll(r);

Best Practices

โœ… Do This:

// Conditional element
var items = [if (includeHeader) 'Header', 'Item'];

// Generate from iteration
var squares = [for (var i = 1; i <= 5; i++) i * i];

// Filter inside collection-for
var evens = [for (var n in numbers) if (n % 2 == 0) n];

// Build map from list
var map = {for (var name in names) name: name.length};

// Combine all three
var args = ['run', if (v) '-v', ...extra, for (var i = 0; i < 2; i++) '$i'];

โŒ Don’t Do This:

// Using a loop to build a simple list
var doubled = <int>[];                    // โŒ use collection-for
for (var n in numbers) doubled.add(n * 2);

// Using a ternary with a sentinel
var items = [include ? 'Header' : null];  // โŒ null in list

// Building a map imperatively
var map = <String, int>{};                // โŒ use collection-for
for (var n in names) map[n] = n.length;

// Nesting loops for a flat list
var flat = <int>[];                       // โŒ use nested collection-for
for (var row in matrix) {
  for (var cell in row) flat.add(cell);
}

Common Pitfalls

PitfallWhy It HappensFix
Null in list from ternaryUsed cond ? x : nullUse collection-if
break in collection-forIt is an expressionUse a loop statement
Modification during iterationBuilding from a changing listBuild from a copy
Map duplicate keysTwo spreads with same keyLater wins; order matters
Type inference issueMixed element typesAnnotate the collection type
Nested collection-for orderWrong nestingOuter loop first

Real-World Examples

1. Conditional Header

var items = [if (showHeader) 'Header', ...body];

2. Command Arguments

var args = ['run', if (verbose) '-v', ...extra];

3. Generated Range

var levels = [for (var i = 0; i < 5; i++) 'level-$i'];

4. Filtered List

var evens = [for (var n in numbers) if (n % 2 == 0) n];

5. Map from List

var lookup = {for (var user in users) user.id: user};

6. Flatten Nested List

var flat = [for (var sub in lists) ...sub];

7. Cart Items with Total

var summary = [
  for (var item in cart)
    '${item.name}: \$${item.price}',
  if (cart.isNotEmpty) 'Total: \$${total}',
];

8. Widget Children

var children = [
  const Header(),
  if (isLoggedIn) const UserMenu(),
  for (var item in items) ItemWidget(item: item),
  const Footer(),
];

9. Set from Filtered Range

var primes = {
  for (var n in numbers)
    if (isPrime(n)) n,
};

10. Deeply Nested

var grid = [
  for (var row in rows)
    [for (var cell in row) transform(cell)],
];

Visual

Collection-If

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  var items = [                                               โ”‚
โ”‚    'always',                                                 โ”‚
โ”‚    if (condition) 'conditional',                             โ”‚
โ”‚    'always',                                                 โ”‚
โ”‚  ];                                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  condition = true  โ†’  ['always', 'conditional', 'always']    โ”‚
โ”‚  condition = false โ†’  ['always', 'always']                   โ”‚
โ”‚                                                              โ”‚
โ”‚  The element is included or omitted based on the condition.  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Collection-For

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  var squares = [                                             โ”‚
โ”‚    for (var i = 1; i <= 5; i++) i * i,                       โ”‚
โ”‚  ];                                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  Iteration 1: i=1 โ†’ 1                                        โ”‚
โ”‚  Iteration 2: i=2 โ†’ 4                                        โ”‚
โ”‚  Iteration 3: i=3 โ†’ 9                                        โ”‚
โ”‚  Iteration 4: i=4 โ†’ 16                                       โ”‚
โ”‚  Iteration 5: i=5 โ†’ 25                                       โ”‚
โ”‚                                                              โ”‚
โ”‚  Result: [1, 4, 9, 16, 25]                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Filter Inside For

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  var evens = [                                               โ”‚
โ”‚    for (var n in numbers)                                    โ”‚
โ”‚      if (n % 2 == 0) n,                                      โ”‚
โ”‚  ];                                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  numbers = [1, 2, 3, 4, 5, 6]                                โ”‚
โ”‚                                                              โ”‚
โ”‚  n=1: 1%2 != 0 โ†’ omitted                                     โ”‚
โ”‚  n=2: 2%2 == 0 โ†’ included                                    โ”‚
โ”‚  n=3: omitted                                                โ”‚
โ”‚  n=4: included                                               โ”‚
โ”‚  n=5: omitted                                                โ”‚
โ”‚  n=6: included                                               โ”‚
โ”‚                                                              โ”‚
โ”‚  Result: [2, 4, 6]                                           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Combining All Three

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  var args = [                                                โ”‚
โ”‚    'build',                 โ† literal                        โ”‚
โ”‚    if (verbose) '--verbose', โ† collection-if                 โ”‚
โ”‚    ...extras,               โ† spread                         โ”‚
โ”‚    for (var i = 0; i < 2; i++) '--level=$i', โ† collection-forโ”‚
โ”‚    'target',                โ† literal                        โ”‚
โ”‚  ];                                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  Result:                                                     โ”‚
โ”‚  [build, --verbose, --color, --progress, --level=0,          โ”‚
โ”‚   --level=1, target]                                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Collection-ifif (cond) element inside a literal
Collection-if elseif (cond) a else b
Collection-forfor (var x in items) element
Range formfor (var i = 0; i < n; i++) element
Works inList, set, and map literals
Composes withSpread (..., ...?)
NestedCollection-if inside collection-for
Filteringfor (...) if (...) element
Not supportedbreak, continue

Key takeaways:

  • Collection-if includes an element conditionally. [if (cond) x] adds x when the condition is true and omits it otherwise. It works in lists, sets, and maps, and supports an else branch.
  • Collection-for includes multiple elements from an iteration. [for (var x in items) f(x)] generates elements for each item. It supports both the in form and the classic for form with an index.
  • Both work in map literals. For a map, the element is a key-value pair: {if (cond) k: v} and {for (var x in items) f(x): g(x)}.
  • Collection-if inside collection-for filters. [for (var n in numbers) if (n > 0) n] generates only the elements that satisfy the condition. This replaces a loop with a condition.
  • Nested collection-for flattens. [for (var row in matrix) for (var cell in row) cell] produces a flat list from a nested structure.
  • Spread and collection-for both add multiple elements. Spread expands an existing iterable; collection-for generates elements. They compose in the same literal.
  • Collection-for is an expression, not a statement. It does not support break or continue. For control flow that requires these, use a loop statement and add.
  • The declarative form is preferred for construction. When a collection is built from fixed elements, conditions, and iterations, the literal form is clearer than a sequence of add calls.

Remember: Collection-if and collection-for are the declarative forms of conditional and iterative inclusion. They turn collection construction from a procedure into a description. A list that conditionally includes a header, generates elements from a range, and spreads an optional collection is a single expression that says exactly what the list contains. This is the same idea as the spread operator: the literal is the specification, and the engine does the building. Use these constructs when the collection is a fixed expression rather than a runtime computation, and fall back to loops when the logic requires break, continue, or intermediate state. Together with spread and the null-aware variants, collection-if and collection-for make Dart’s collection literals one of the most expressive parts of the language.



Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!