joinDisplayList method
Joins these strings into a natural-language list with an Oxford comma:
one item is itself, two become 'a and b', three or more become
'a, b, and c'.
Each entry is trimmed and blank/whitespace-only entries are dropped before
counting, so [' ', 'a', ''] collapses to a single item rather than
emitting stray separators. When isUnique is true (default) duplicates
are removed via toUnique (first-seen order preserved). Returns null —
not '' — when nothing remains after trimming, so a caller can tell
"no items" apart from a real joined string.
The joiners are caller-controlled for locale/style:
joinerseparates the leading items in the 3+ case (default', ').doubleJoinerjoins exactly two items (default' and ').lastJoinerprecedes the final item in the 3+ case (default', and ', the Oxford comma).
Example:
['Alice', 'Bob', 'Carol'].joinDisplayList(); // 'Alice, Bob, and Carol'
['Alice', 'Bob'].joinDisplayList(); // 'Alice and Bob'
['Alice'].joinDisplayList(); // 'Alice'
<String>[].joinDisplayList(); // null
Audited: 2026-06-12 11:26 EDT
Implementation
@useResult
String? joinDisplayList({
String joiner = ', ',
String doubleJoiner = ' and ',
String lastJoiner = ', and ',
bool isUnique = true,
}) {
// Trim and drop blanks before counting so the length-based branching below
// sees the real item count, not entries that would render as empty.
final List<String> trimmed = <String>[
for (final String s in this)
if (s.trim().isNotEmpty) s.trim(),
];
final List<String> list = isUnique ? trimmed.toUnique() : trimmed;
if (list.isEmpty) {
return null;
}
// first/last are safe here: each branch runs only after its length is
// proven, so the list is never empty at the access site.
if (list.length == 1) {
return list.first;
}
if (list.length == 2) {
return '${list.first}$doubleJoiner${list.last}';
}
// 3+ items: lead items joined by [joiner], then the Oxford [lastJoiner].
return list.takeSafe(list.length - 1).join(joiner) + lastJoiner + list.last;
}