集合
Dart 內建支援列表 (list)、集合 (set) 和對映 (map) 集合。要了解有關配置集合中包含的型別,請查閱泛型。
列表
#在幾乎所有程式語言中,最常見的集合可能是陣列,或稱有序物件組。在 Dart 中,陣列是 List 物件,因此大多數人直接稱它們為列表。
Dart 列表字面量由用方括號 ([]) 括起來的逗號分隔的元素列表表示。每個元素通常是一個表示式。以下是一個簡單的 Dart 列表:
var list = [1, 2, 3];您可以在 Dart 集合字面量中的最後一項後新增逗號。這個尾隨逗號不會影響集合,但有助於防止複製貼上錯誤。
var list = ['Car', 'Boat', 'Plane'];列表使用基於零的索引,其中 0 是第一個元素的索引,list.length - 1 是最後一個元素的索引。您可以使用 .length 屬性獲取列表的長度,並使用下標運算子 ([]) 訪問列表的元素。
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);要建立編譯時常量列表,請在列表字面量前新增 const。
var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.有關列表的更多資訊,請參閱 dart:core 文件中的列表部分。
集合
#Dart 中的集合 (set) 是唯一元素的無序集合。Dart 透過集合字面量和 Set 型別提供對集合的支援。
以下是一個使用集合字面量建立的簡單 Dart 集合:
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};要建立一個空集合,請使用 {} 並在其前加上型別引數,或將 {} 賦值給 Set 型別的變數。
var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.使用 add() 或 addAll() 方法向現有集合新增項:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);使用 .length 獲取集合中的項數:
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);要建立編譯時常量集合,請在集合字面量前新增 const。
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // This line will cause an error.有關集合的更多資訊,請參閱 dart:core 文件中的集合部分。
對映
#在對映中,每個元素都是一個鍵值對。鍵值對中的每個鍵都與一個值關聯,並且鍵和值都可以是任何型別的物件。每個鍵只能出現一次,儘管相同的值可以與多個不同的鍵關聯。Dart 透過對映字面量和 Map 型別提供對對映的支援。
以下是幾個使用對映字面量建立的簡單 Dart 對映:
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings',
};
var nobleGases = {2: 'helium', 10: 'neon', 18: 'argon'};您可以使用對映建構函式建立相同的物件:
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map<int, String>();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';使用下標賦值運算子 ([]=) 向現有對映新增新的鍵值對:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair使用下標運算子 ([]) 從對映中檢索值:
var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');如果您查詢對映中不存在的鍵,將返回 null。
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);使用 .length 獲取對映中的鍵值對數量:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);要建立編譯時常量對映,請在對映字面量前新增 const。
final constantMap = const {2: 'helium', 10: 'neon', 18: 'argon'};
// constantMap[2] = 'Helium'; // This line will cause an error.有關對映的更多資訊,請參閱 dart:core 文件中的對映部分。
集合元素
#集合字面量包含一系列元素。在執行時,每個元素都會被評估,產生零個或多個值,然後這些值被插入到結果集合中。這些元素分為兩大類:葉元素和控制流元素。
葉元素:將單個項插入到集合字面量中。
表示式元素:評估單個表示式並將結果值插入到集合中。
對映條目元素:評估一對鍵和值表示式並將結果條目插入到集合中。
控制流元素:有條件地或迭代地向周圍集合新增零個或多個值。
空感知元素:評估一個表示式,如果結果不為
null,則將該值插入到周圍集合中。展開元素:迭代給定序列(集合表示式)並將所有結果值插入到周圍集合中。
空感知展開元素:與展開元素類似,但允許集合為
null,如果為null則不插入任何內容。If 元素:根據給定的條件表示式有條件地評估一個內部元素,如果條件為假,則可選地評估另一個
else元素。For 元素:迭代並重複評估給定的內部元素,插入零個或多個結果值。
要了解有關集合元素的更多資訊,請參閱以下部分。
表示式元素
#表示式元素評估單個表示式並將結果值插入到集合中。此表示式可以包含各種構造,如字面量、變數、運算子、函式呼叫和建構函式呼叫。
表示式元素在集合中具有以下語法:
<expression>對映條目元素
#對映條目元素評估一對鍵和值表示式並將結果條目插入到集合中。該對中的鍵和值都可以是表示式。
對映條目元素在集合中具有以下語法:
<key_expression>: <value_expression>空感知元素
#空感知元素評估一個表示式,如果結果不為 null,則將該值插入到周圍集合中。
空感知元素在表示式元素中具有以下語法:
?<expression>空感知元素在對映條目元素中具有以下語法:
// key is a null-aware element
?<key_expression>: <value_expression>// value is a null-aware element
<key_expression>: ?<value_expression>// key and value are null-aware elements
?<key_expression>: ?<value_expression>在以下示例中,空感知元素 ?a 的結果不會新增到名為 items 的列表中,因為 a 為 null。
int? absentValue = null;
int? presentValue = 3;
var items = [
1,
?absentValue,
?presentValue,
absentValue,
5,
]; // [1, 3, null, 5]以下示例說明了在對映條目元素內部使用空感知元素的各種方式:
String? presentKey = 'Apple';
String? absentKey = null;
int? presentValue = 3;
int? absentValue = null;
var itemsA = {presentKey: absentValue}; // {Apple: null}
var itemsB = {presentKey: ?absentValue}; // {}
var itemsC = {absentKey: presentValue}; // {null: 3}
var itemsD = {?absentKey: presentValue}; // {}
var itemsE = {absentKey: absentValue}; // {null: null}
var itemsF = {?absentKey: ?absentValue}; // {}展開元素
#展開元素迭代給定序列並將所有結果值插入到周圍集合中。
展開元素在集合中具有以下語法。序列表達式可以表示評估為實現 Iterable 介面的物件的任何表示式。
...<sequence_expression>在以下示例中,名為 a 的列表中的元素被新增到名為 items 的列表中。
var a = [1, 2, null, 4];
var items = [0, ...a, 5]; // [0, 1, 2, null, 4, 5]如果您要展開一個可能評估為 null 的表示式,並且希望忽略該 null (且不插入任何元素),請使用空感知展開元素。
要了解有關展開運算子的更多資訊,請參閱展開運算子。
空感知展開元素
#空感知展開元素與展開元素類似,但允許集合為 null,如果為 null 則不插入任何內容。
空感知展開元素在集合中具有以下語法:
...?<sequence_expression>在以下示例中,名為 a 的列表被忽略,因為它為 null,但名為 b 的列表中的元素被新增到名為 items 的列表中。請注意,如果集合本身不為 null,但包含為 null 的元素,則這些 null 元素仍將新增到結果中。
List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]由於空安全,您不能對可能為 null 的值執行展開操作 (...)。以下示例將產生編譯時錯誤,因為 extraOptions 引數可為空,並且在 extraOptions 上使用的展開運算子不是空感知的。
List<String> buildCommandLine(
String executable,
List<String> options, [
List<String>? extraOptions,
]) {
return [
executable,
...options,
...extraOptions, // <-- Error
];
}
// Usage:
// buildCommandLine('dart', ['run', 'my_script.dart'], null);
// Result:
// Compile-time error如果您想展開一個可為空的集合,請使用空感知展開元素。以下示例有效,因為在 extraOptions 上使用了空感知展開運算子。
List<String> buildCommandLine(
String executable,
List<String> options, [
List<String>? extraOptions,
]) {
return [
executable,
...options,
...?extraOptions, // <-- OK now.
];
}
// Usage:
// buildCommandLine('dart', ['run', 'my_script.dart'], null);
// Result:
// [dart, run, my_script.dart]要了解有關空感知展開運算子的更多資訊,請參閱展開運算子。
If 元素
#if 元素根據給定的條件表示式有條件地評估一個內部元素,如果條件為假,則可選地評估另一個 else 元素。
if 元素有幾種語法變體:
// If the bool expression is true, include the result.
if (<bool_expression>) <result>// If the expression matches the pattern, include the result.
if (<expression> case <pattern>) <result>// If the operation resolves as true, include the first
// result, otherwise, include the second result.
if (<bool_expression>) <result> else <result>// If the operation resolves as true, include the first
// result, otherwise, include the second result.
if (<expression> case <pattern>) <result> else <result>以下示例說明了在集合中使用帶有布林表示式的 if 元素的各種方式:
var includeItem = true;
var items = [0, if (includeItem) 1, 2, 3]; // [0, 1, 2, 3]var includeItem = true;
var items = [0, if (!includeItem) 1, 2, 3]; // [0, 2, 3]var name = 'apple';
var items = [0, if (name == 'orange') 1 else 10, 2, 3]; // [0, 10, 2, 3]var name = 'apple';
var items = [
0,
if (name == 'kiwi') 1 else if (name == 'pear') 10,
2,
3,
]; // [0, 2, 3]以下示例說明了在集合中使用帶有 case 部分的 if 元素的各種方式:
Object data = 123;
var typeInfo = [
if (data case int i) 'Data is an integer: $i',
if (data case String s) 'Data is a string: $s',
if (data case bool b) 'Data is a boolean: $b',
if (data case double d) 'Data is a double: $d',
]; // [Data is an integer: 123, Data is a double: 123]var word = 'hello';
var items = [
1,
if (word case String(length: var wordLength)) wordLength,
3,
]; // [1, 5, 3]var orderDetails = ['Apples', 12, ''];
var summary = [
'Product: ${orderDetails[0]}',
if (orderDetails case [_, int qty, _]) 'Quantity: $qty',
if (orderDetails case [_, _, ''])
'Delivery: Not Started'
else
'Delivery: In Progress',
]; // [Product: Apples, Quantity: 12, Delivery: Not Started]您可以將不同的 if 操作與 else if 部分混合使用。例如:
var a = 'apple';
var b = 'orange';
var c = 'mango';
var items = [
0,
if (a == 'apple') 1 else if (a case 'mango') 10,
if (b case 'pear') 2 else if (b == 'mango') 20,
if (c case 'apple') 3 else if (c case 'mango') 30,
4,
]; // [0, 1, 30, 4]要了解有關 if 條件的更多資訊,請參閱if 語句。要了解有關 if-case 條件的更多資訊,請參閱if-case 語句。
For 元素
#for 元素迭代並重複評估給定的內部元素,插入零個或多個結果值。
for 元素在集合中具有以下語法:
for (<expression> in <collection>) <result>for (<initialization_clause>; <condition_clause>; <increment_clause>) <result>以下示例說明了在集合中使用 for 元素的各種方式:
var numbers = [2, 3, 4];
var items = [1, for (var n in numbers) n * n, 7]; // [1, 4, 9, 16, 7]var items = [1, for (var x = 5; x > 2; x--) x, 7]; // [1, 5, 4, 3, 7]var items = [1, for (var x = 2; x < 4; x++) x, 7]; // [1, 2, 3, 7]要了解有關 for 迴圈的更多資訊,請參閱for 迴圈。
巢狀控制流元素
#您可以將控制流元素相互巢狀。這是一種替代其他語言中列表推導式的強大方法。
在以下示例中,只有 numbers 中的偶數包含在 items 中。
var numbers = [1, 2, 3, 4, 5, 6, 7];
var items = [
0,
for (var n in numbers)
if (n.isEven) n,
8,
]; // [0, 2, 4, 6, 8]在 if 或 for 元素內部立即對集合字面量使用展開操作是常見且符合習慣的做法。例如:
var items = [
if (condition) oneThing(),
if (condition) ...[multiple(), things()],
]; // [oneThing, [multiple_a, multiple_b], things]您可以任意深度地巢狀各種元素。在以下示例中,if、for 和展開元素在集合中相互巢狀:
var nestItems = true;
var ys = [1, 2, 3, 4];
var items = [
if (nestItems) ...[
for (var x = 0; x < 3; x++)
for (var y in ys)
if (x < y) x + y * 10,
],
]; // [10, 20, 30, 40, 21, 31, 41, 32, 42]