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
| Form | Example |
|---|---|
| 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
| Form | Example |
|---|---|
| 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
| Combination | Example |
|---|---|
| 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
| Declarative | Imperative |
|---|---|
[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
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Null in list from ternary | Used cond ? x : null | Use collection-if |
break in collection-for | It is an expression | Use a loop statement |
| Modification during iteration | Building from a changing list | Build from a copy |
| Map duplicate keys | Two spreads with same key | Later wins; order matters |
| Type inference issue | Mixed element types | Annotate the collection type |
| Nested collection-for order | Wrong nesting | Outer 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
| Item | Value |
|---|---|
| Collection-if | if (cond) element inside a literal |
| Collection-if else | if (cond) a else b |
| Collection-for | for (var x in items) element |
| Range form | for (var i = 0; i < n; i++) element |
| Works in | List, set, and map literals |
| Composes with | Spread (..., ...?) |
| Nested | Collection-if inside collection-for |
| Filtering | for (...) if (...) element |
| Not supported | break, continue |
Key takeaways:
- Collection-if includes an element conditionally.
[if (cond) x]addsxwhen the condition is true and omits it otherwise. It works in lists, sets, and maps, and supports anelsebranch. - Collection-for includes multiple elements from an iteration.
[for (var x in items) f(x)]generates elements for each item. It supports both theinform and the classicforform 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
breakorcontinue. For control flow that requires these, use a loop statement andadd. - 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
addcalls.
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!