Dart 中的列表推导式
最后修改于 2025 年 6 月 8 日
本教程将使用 collection if
和 for
语法来探讨 Dart 中的列表推导式。列表推导式允许您以一种简洁、声明式的方式创建和转换列表,这与 Python 的列表推导式类似。
列表推导式概述
Dart 提供了两种强大的声明式列表构建构造:collection if
和 collection for
。它们允许您在列表字面量中直接使用条件元素和迭代转换来创建列表。
构造 | 语法 | 目的 |
---|---|---|
collection if | if (condition) element |
有条件地包含元素 |
collection for | for (var in iterable) element |
转换/生成元素 |
spread | ...iterable |
包含多个元素 |
spread with null | ...?iterable |
有条件地包含元素 |
这些构造可以组合起来,以一种简洁、可读的方式创建复杂的列表转换。它们在 Flutter UI 代码中构建小部件列表时尤其有用。
基本 Collection If
collection if
构造有条件地将元素包含在列表中。此示例展示了在创建期间过滤列表元素的各种方法。
void main() { bool includeNegatives = false; var numbers = [-2, -1, 0, 1, 2]; // Simple conditional inclusion var filtered = [ for (var n in numbers) if (n >= 0) n ]; print('Filtered: $filtered'); // Conditional element with else var absolute = [ for (var n in numbers) if (n >= 0 || includeNegatives) n else -n ]; print('Absolute: $absolute'); // Multiple conditions var user = {'name': 'Alice', 'age': 30, 'isAdmin': true}; var permissions = [ 'view', if (user['age'] as int >= 18) 'edit', if (user['isAdmin'] == true) ...[ 'delete', 'configure' ], ]; print('Permissions: $permissions'); // With spread operator var defaultItems = ['home', 'search']; var extraItems = ['profile', 'settings']; var allItems = [ ...defaultItems, if (user['isAdmin'] == true) ...extraItems, 'logout' ]; print('All items: $allItems'); }
第一个示例过滤掉负数。第二个示例展示了在条件失败时如何包含交替元素。第三个示例演示了多个条件和嵌套的 spread 以实现管理员权限。
spread 运算符 (...
) 对于有条件地组合多个列表特别有用。
$ dart run basic_if.dart Filtered: [0, 1, 2] Absolute: [2, 1, 0, 1, 2] Permissions: [view, edit, delete, configure] All items: [home, search, profile, settings, logout]
基本 Collection For
collection for
构造转换或生成列表元素。此示例展示了各种转换模式。
void main() { // Simple transformation var numbers = [1, 2, 3]; var squares = [for (var n in numbers) n * n]; print('Squares: $squares'); // Nested loops var pairs = [ for (var i = 1; i <= 3; i++) for (var j = 1; j <= 2; j++) '($i,$j)' ]; print('Pairs: $pairs'); // Complex transformations var users = [ {'name': 'Alice', 'roles': ['admin', 'user']}, {'name': 'Bob', 'roles': ['user']}, {'name': 'Charlie', 'roles': ['user', 'editor']} ]; var roleList = [ for (var user in users) for (var role in user['roles'] as List<String>) '${user['name']} ($role)' ]; print('Roles: $roleList'); // Combining with spread var matrix = [ [1, 2], [3, 4], [5, 6] ]; var flattened = [ 0, for (var row in matrix) ...row, 7 ]; print('Flattened: $flattened'); }
示例展示了数字转换、用于生成对的嵌套循环、复杂对象转换以及矩阵展平。collection for
语法通常消除了对临时变量和命令式循环的需求。
请注意,嵌套循环如何在单个表达式中展平层次化数据结构。这在处理 API 响应或配置数据时尤其有用。
$ dart run basic_for.dart Squares: [1, 4, 9] Pairs: [(1,1), (1,2), (2,1), (2,2), (3,1), (3,2)] Roles: [Alice (admin), Alice (user), Bob (user), Charlie (user), Charlie (editor)] Flattened: [0, 1, 2, 3, 4, 5, 6, 7]
组合 If 和 For
collection if
和 collection for
可以组合起来实现强大的列表推导式。此示例演示了复杂的过滤和转换。
class Product { final String name; final double price; final bool inStock; Product(this.name, this.price, this.inStock); @override String toString() => '$name (\$$price)'; } void main() { var products = [ Product('Laptop', 999.99, true), Product('Phone', 699.99, false), Product('Tablet', 499.99, true), Product('Monitor', 249.99, true), Product('Keyboard', 79.99, false), ]; // Filter and transform var availableProducts = [ for (var p in products) if (p.inStock) p.name.toUpperCase() ]; print('Available: $availableProducts'); // Complex conditions var discounted = [ for (var p in products) if (p.inStock) if (p.price > 500) Product('Premium ${p.name}', p.price * 0.9, true) else Product(p.name, p.price * 0.95, true) ]; print('Discounted: $discounted'); // Real-world example: Widget list var features = ['dark_mode', 'notifications', 'advanced_settings']; var userPermissions = ['dark_mode', 'notifications']; var featureWidgets = [ for (var feature in features) if (userPermissions.contains(feature)) '${feature.replaceAll('_', ' ')} widget' else 'disabled ${feature.replaceAll('_', ' ')} widget' ]; print('Feature widgets: $featureWidgets'); }
第一个推导式过滤了有库存的产品并转换了它们的名称。第二个根据价格应用不同的折扣。第三个展示了一个真实的 UI 场景,根据权限构建小部件描述。
这些推导式在执行复杂操作的同时保持了可读性。嵌套的 if
语句演示了如何在单个表达式中处理多个条件。
$ dart run combined.dart Available: [LAPTOP, TABLET, MONITOR] Discounted: [Premium Laptop ($899.991), Tablet ($474.9905), Monitor ($237.4905)] Feature widgets: [dark mode widget, notifications widget, disabled advanced settings widget]
高级模式
对于更高级的场景,列表推导式可以嵌套并与其他 Dart 功能结合使用。此示例演示了复杂的数据处理。
class Student { final String name; final List<int> grades; final bool isActive; Student(this.name, this.grades, this.isActive); } void main() { var students = [ Student('Alice', [85, 92, 78], true), Student('Bob', [65, 70, 80], true), Student('Charlie', [90, 88, 95], false), ]; // Complex transformation with nested comprehensions var reportCards = [ for (var student in students) if (student.isActive) { 'name': student.name, 'average': student.grades.reduce((a, b) => a + b) / student.grades.length, 'grades': [ for (var grade in student.grades) if (grade >= 70) 'Pass' else 'Fail' ], } ]; print('Report cards:'); for (var card in reportCards) { print('${card['name']}: ${(card['average'] as double).toStringAsFixed(1)}'); print(' Grades: ${card['grades']}'); } // Matrix operations var matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]; var transposed = [ for (var i = 0; i < matrix[0].length; i++) [ for (var row in matrix) row[i] ] ]; print('\nOriginal matrix: $matrix'); print('Transposed matrix: $transposed'); }
第一个示例将学生数据处理成带有平均分和及格/不及格等级的报告卡。第二个示例使用带索引的嵌套推导式执行矩阵转置。
这些模式展示了列表推导式如何简洁地处理实际数据处理任务。矩阵转置作为单个表达式尤其令人印象深刻。
$ dart run advanced.dart Report cards: Alice: 85.0 Grades: [Pass, Pass, Pass] Bob: 71.7 Grades: [Fail, Pass, Pass] Original matrix: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] Transposed matrix: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
来源
Dart 的 collection if
和 for
语法提供了强大的列表推导式功能。虽然与 Python 风格的推导式不同,但这些构造实现了声明式的列表创建和转换。它们在 Flutter UI 代码和数据处理管道中尤其有价值。
作者
列出 所有 Dart 教程。