Dart 列表的 sort()
方法提供高效的排序功能,直接修改原始列表而非建立新列表。插入和刪除操作的效能取決於操作位置,在列表頭或中間操作可能觸發元素移動,影響效能。對於頻繁的插入刪除操作,尤其在列表頭部,連結串列是更優的選擇,其指標連線的結構特性使其更擅長此類操作。
列表是 Dart 中常用的資料結構,分為可變與不可變兩種。可變列表使用 var
或 final
關鍵字宣告,並可透過 add
、remove
、insert
等方法修改內容。不可變列表則使用 const
關鍵字宣告,其內容一旦確定便無法更改,任何修改嘗試都會導致錯誤。List.unmodifiable
建構子則允許根據現有列表建立不可變版本。
Dart 也提供空安全特性以處理可空列表和列表中的可空元素。?.
運運算元允許安全地訪問成員,??
運運算元則提供預設值以避免空值錯誤。集合(Set)是不允許重複元素的資料結構,常用於快速檢查元素是否存在。add
、remove
、contains
、union
、intersection
和 difference
等方法提供了集合的基本操作功能。
列表排序
Dart 中的列表可以使用 sort()
方法進行排序。這個方法會就地排序列表,意味著它不會建立一個新的列表,而是直接修改原始列表。
void main() {
final integers = [32, 73, 2, 343, 7, 10, 1];
integers.sort();
print(integers); // [1, 2, 7, 10, 32, 73, 343]
}
在上面的例子中,integers
列表被排序後,元素按照從小到大的順序排列。
列表插入和刪除
當您需要在列表中插入或刪除元素時,Dart 提供了多種方法。然而,當您需要在列表的開始或中間插入或刪除元素時,Dart 需要內部移動元素,這可能會影響效能。
void main() {
final list = [1, 2, 3, 4, 5];
list.insert(0, 0); // 在列表開始插入元素
print(list); // [0, 1, 2, 3, 4, 5]
list.removeAt(0); // 刪除列表中的第一個元素
print(list); // [1, 2, 3, 4, 5]
}
在上面的例子中,insert()
方法被用來在列表的開始插入一個元素,而 removeAt()
方法被用來刪除列表中的第一個元素。
使用連結串列
如果您需要在列表中頻繁插入或刪除元素,特別是在列表的開始或中間,使用連結串列(Linked List)可能是一個更好的選擇。連結串列是一種資料結構,它的元素之間透過指標連線,允許高效地插入和刪除元素。
內容解密:
sort()
方法就地排序列表,意味著它不會建立一個新的列表,而是直接修改原始列表。- 列表插入和刪除操作可能會影響效能,特別是在列表的開始或中間。
- 連結串列是一種資料結構,它的元素之間透過指標連線,允許高效地插入和刪除元素。
圖表翻譯:
flowchart TD A[列表] --> B[排序] B --> C[插入/刪除] C --> D[連結串列] D --> E[高效插入/刪除]
在上面的流程圖中,列表可以被排序,然後可以進行插入和刪除操作。如果需要高效地插入和刪除元素,連結串列是一個更好的選擇。
Dart 中的列表(List)
Dart 中的列表是一種集合,允許您儲存多個值。列表可以是可變的(mutable)或不可變的(immutable)。
建立列表
您可以使用 []
符號建立一個列表。例如:
var fruits = ['apple', 'banana', 'orange'];
可變列表
可變列表可以使用 var
或 final
關鍵字宣告。例如:
var desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
final desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
您可以使用 add
、remove
和 insert
方法修改可變列表的內容。例如:
desserts.add('ice cream');
desserts.remove('cookies');
desserts.insert(0, 'cake');
不可變列表
不可變列表可以使用 const
關鍵字宣告。例如:
const desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
不可變列表的內容不能被修改。任何嘗試修改其內容的操作都會導致編譯錯誤。
列表方法
Dart 中的列表提供了多種方法,例如 sort
、indexOf
、removeAt
等。例如:
var numbers = [4, 2, 7, 1];
numbers.sort();
print(numbers); // [1, 2, 4, 7]
var index = numbers.indexOf(2);
print(index); // 1
numbers.removeAt(1);
print(numbers); // [1, 4, 7]
練習
建立一個名為 months
的列表,並將 12 個月份的名稱新增到其中。然後,找到 “March” 的索引,並將其從列表中刪除。最後,將 “March” 插入到正確的位置,並列印列表的內容。
var months = [];
months.add('January');
months.add('February');
months.add('March');
months.add('April');
months.add('May');
months.add('June');
months.add('July');
months.add('August');
months.add('September');
months.add('October');
months.add('November');
months.add('December');
var index = months.indexOf('March');
months.removeAt(index);
months.insert(2, 'March');
print(months);
Dart 中的不可變列表
在 Dart 中,const
關鍵字可以用來宣告一個不可變的列表。例如:
const desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
由於 const
關鍵字的存在,該列表不能被修改。試圖新增、移除或更新列表中的元素將會導致執行時錯誤。
使用 const
列表字面量
如果你不能使用 const
關鍵字宣告變數本身,你可以使用 const
列表字面量來建立一個深度不可變的列表。例如:
final desserts = const ['cookies', 'cupcakes', 'donuts', 'pie'];
這種情況可能出現在提供類別中的預設值時。例如:
class Desserts {
Desserts([this.desserts = const ['cookies']]);
final List<String> desserts;
}
在這種情況下,desserts
是 final
的,但預設值是一個 const
列表字面量。這確保了預設列表的內容不能被修改。
使用 List.unmodifiable
建構子
如果你想要建立一個不可變的列表,但元素值在執行時才會知道,你可以使用 List.unmodifiable
建構子。例如:
final modifiableList = [DateTime.now(), DateTime.now()];
final unmodifiableList = List.unmodifiable(modifiableList);
在這種情況下,modifiableList
是一個可變的列表,但 unmodifiableList
是一個不可變的列表。
列表屬性
Dart 中的列表有幾個有用的屬性。以下是一個示例列表:
const drinks = ['water', 'milk', 'juice', 'soda'];
存取第一個和最後一個元素
你可以使用 first
和 last
屬性存取列表中的第一個和最後一個元素。例如:
drinks.first // 'water'
drinks.last // 'soda'
這與使用索引存取元素等效:
drinks[0] // 'water'
drinks[drinks.length - 1] // 'soda'
檢查列表是否為空
你可以使用 isEmpty
和 isNotEmpty
屬性檢查列表是否為空。例如:
drinks.isEmpty // false
drinks.isNotEmpty // true
這與以下程式碼等效:
drinks.length == 0 // false
drinks.length > 0 // true
圖表翻譯:
graph LR A[列表] -->|first|> B[第一個元素] A -->|last|> C[最後一個元素] A -->|isEmpty|> D[是否為空] A -->|isNotEmpty|> E[是否不為空]
Lists 和 Dart
在 Dart 中,Lists 是一個非常重要的資料結構,允許你儲存和操作多個元素。這篇文章將介紹如何使用 Lists、迴圈和操作 Lists 的方法。
Lists 的基本操作
你可以使用 const
關鍵字宣告一個 List,並使用索引存取其元素。例如:
const desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
print(desserts[0]); // cookies
你也可以使用 length
屬性取得 List 的元素數量:
print(desserts.length); // 4
迴圈和 Lists
當你需要對 List 的每個元素進行操作時,迴圈是一個很好的工具。你可以使用 for
迴圈或 for-in
迴圈。
使用 for
迴圈
const desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
for (int i = 0; i < desserts.length; i++) {
final item = desserts[i];
print('I like $item.');
}
使用 for-in
迴圈
const desserts = ['cookies', 'cupcakes', 'donuts', 'pie'];
for (final item in desserts) {
print('I also like $item!');
}
Lists 的操作
你可以使用 addAll
方法將另一個 List 的元素新增到目前的 List 中:
const pastries = ['cookies', 'croissants'];
const candy = ['Junior Mints', 'Twizzlers', 'M&Ms'];
final desserts = ['donuts'];
desserts.addAll(pastries);
你也可以使用 spread operator
(...
) 將兩個 List 合併:
const pastries = ['cookies', 'croissants'];
const candy = ['Junior Mints', 'Twizzlers', 'M&Ms'];
final desserts = ['donuts', ...pastries, ...candy];
練習
- 將以下 List 中的每個數字的平方輸出:
const numbers = [1, 2, 4, 7];
使用 for
迴圈和 for-in
迴圈分別解決這個問題。
- 使用
spread operator
將兩個 List 合併:
const pastries = ['cookies', 'croissants'];
const candy = ['Junior Mints', 'Twizzlers', 'M&Ms'];
Dart 中的列表操作
Dart 提供了多種方式來操作列表,包括新增元素、合併列表和條件式包含元素。
新增元素
可以使用 addAll
方法將一個列表的元素新增到另一個列表中。例如:
void main() {
List<String> desserts = ['donuts'];
List<String> pastries = ['cookies', 'croissants'];
List<String> candy = ['Junior Mints', 'Twizzlers', 'M&Ms'];
desserts.addAll(pastries);
desserts.addAll(candy);
print(desserts);
}
這將輸出:[donuts, cookies, croissants, Junior Mints, Twizzlers, M&Ms]
合併列表
Dart 也提供了 spread operator (...
) 來合併列表。例如:
void main() {
List<String> desserts = ['donuts', ...['cookies', 'croissants'], ...['Junior Mints', 'Twizzlers', 'M&Ms']];
print(desserts);
}
這將輸出:[donuts, cookies, croissants, Junior Mints, Twizzlers, M&Ms]
條件式包含元素
可以使用 collection if 來條件式包含元素。例如:
void main() {
bool peanutAllergy = true;
List<String> sensitiveCandy = [
'Junior Mints',
'Twizzlers',
if (!peanutAllergy) 'Reeses',
];
print(sensitiveCandy);
}
這將輸出:[Junior Mints, Twizzlers]
集合迴圈
可以使用 collection for 來生成元素。例如:
void main() {
List<String> deserts = ['gobi', 'sahara', 'arctic'];
List<String> bigDeserts = [
'ARABIAN',
for (var desert in deserts) desert.toUpperCase(),
];
print(bigDeserts);
}
這將輸出:[ARABIAN, GOBI, SAHARA, ARCTIC]
圖表翻譯:
graph LR A[列表操作] --> B[新增元素] A --> C[合併列表] A --> D[條件式包含元素] A --> E[集合迴圈] B --> F[使用addAll方法] C --> G[使用spread operator] D --> H[使用collection if] E --> I[使用collection for]
這個圖表展示了 Dart 中的列表操作,包括新增元素、合併列表、條件式包含元素和集合迴圈。
處理可空列表
在 Dart 中,列表可以是可空的,也可以包含可空的元素。瞭解如何處理這些情況是非常重要的。
可空列表
首先,讓我們看看可空列表的例子:
List<int>? nullableList = [2, 4, 3, 7];
nullableList = null;
在這個例子中,nullableList
是一個可空的列表,意味著它可以是 null
。注意,在列表型別後面加上了 ?
,這表示列表本身是可空的。
可空元素
接下來,讓我們看看列表中包含可空元素的例子:
List<int?> nullableElements = [2, 4, null, 3, 7];
在這個例子中,nullableElements
是一個列表,包含可空的整數元素。注意,在列表型別後面加上了 ?
,這表示列表中的元素是可空的。
可空列表與可空元素
最後,讓我們看看可空列表與可空元素的組合:
List<int?>? nullableListAndElements = [2, 4, null, 3, 7];
nullableListAndElements = null;
在這個例子中,nullableListAndElements
是一個可空的列表,包含可空的整數元素。
使用基本的空值感知運運算元
在處理可空列表或可空元素時,可以使用基本的空值感知運運算元。例如:
List<String?>? drinks = ['milk', 'water', null, 'soda'];
for (String? drink in drinks) {
int letters = drink?.length ?? 0;
print(letters);
}
在這個例子中,使用 ?.
空值感知運運算元來存取 drink
的 length
屬性,如果 drink
是 null
,則傳回 0
。
內容解密:
在上面的例子中,使用 for
迴圈來迭代 drinks
列表。雖然列表是可空的,但 Dart 使用流分析來確定列表已經被指定,因此可以直接迭代元素。使用 ?.
空值感知運運算元來存取 drink
的 length
屬性,如果 drink
是 null
,則傳回 0
。
圖表翻譯:
flowchart TD A[開始] --> B[迭代列表] B --> C[存取元素的 length 屬性] C --> D[使用 ?. 空值感知運運算元] D --> E[傳回 0 如果元素是 null] E --> F[印出結果]
在這個圖表中,展示了迭代列表、存取元素的 length
屬性、使用 ?.
空值感知運運算元、傳回 0
如果元素是 null
,以及印出結果的流程。
Dart 中的列表
Dart 的列表是一種有序的集合,允許您儲存和操作多個元素。列表的元素可以是任何型別的物件,包括字串、整數和其他列表。
列表的建立
您可以使用 []
符號建立一個列表,例如:
List<String> fruits = ['apple', 'banana', 'orange'];
列表的索引
列表的索引從 0 開始,您可以使用 []
符號訪問列表的元素,例如:
print(fruits[0]); // 輸出:apple
列表的可變性
列表的元素是可變的,您可以使用 []
符號修改列表的元素,例如:
fruits[0] = 'grape';
print(fruits); // 輸出:[grape, banana, orange]
列表的迭代
您可以使用 for-in
迴圈迭代列表的元素,例如:
for (var fruit in fruits) {
print(fruit);
}
列表的展開
您可以使用 ...
符號展開一個列表,例如:
List<String> moreFruits = ['watermelon', 'mango'];
fruits = [...fruits, ...moreFruits];
print(fruits); // 輸出:[grape, banana, orange, watermelon, mango]
列表的條件建立
您可以使用 collection if
和 collection for
建立列表的內容,例如:
List<int> numbers = [1, 2, 3, 4, 5];
List<int> evenNumbers = [for (var number in numbers) if (number % 2 == 0) number];
print(evenNumbers); // 輸出:[2, 4]
列表的空安全操作
Dart 提供了兩個空安全運算子:?[]
和 ...?
。這些運算子允許您安全地訪問和操作可能為空的列表。
例如:
List<String>? nullableList;
String? element = nullableList?[0];
print(element); // 輸出:null
挑戰
- 找到列表中最長和最短的字串。
- 判斷列表中是否包含重複的元素。
- 實作一個排序演算法來排序整數列表,不使用
sort
方法。
關鍵點
- 列表儲存有序的集合。
- 列表的元素可以使用零基索引訪問。
- 列表的元素是可變的。
for-in
迴圈是迭代列表元素的方便方式。- 展開運算子 (
...
) 允許您展開一個列表。 - 集合條件和迴圈可以用於建立列表的內容。
- 空安全運算子 (
?[]
和...?
) 提供了額外的方式來處理可能為空的列表。
什麼是集合?
在數學中,集合是一組元素的集合,其中元素的順序不重要,且不允許重複的元素。在Dart中,集合的定義與數學中的定義非常相似。集合是一組元素的集合,其中元素的順序不重要,且不允許重複的元素。
集合的特性
集合的特性與列表(list)不同,列表中的元素的順序是重要的,且允許重複的元素。由於集合的特性,集合可以比列表更快地執行某些操作,特別是在處理大資料集時。這使得集合非常適合快速檢查元素是否存在於集合中。
建立集合
你可以使用Set
型別注釋建立一個空集合,如下所示:
final Set<int> someSet = {};
這個語法告訴Dart,這個集合只允許整數。你也可以使用更短的語法:
final someSet = <int>{};
你也可以使用集合字面量建立集合:
final anotherSet = {1, 2, 3, 1};
由於集合字面量只包含整數,Dart可以推斷出集合的型別為Set<int>
。
集合操作
以下是一些集合操作的例子:
檢查集合內容
你可以使用contains
方法檢查集合是否包含某個元素:
final desserts = {'cake', 'pie', 'donut'};
print(desserts.contains('cake')); // true
print(desserts.contains('cookies')); // false
contains
方法傳回一個布林值,指示集合是否包含指定的元素。
新增元素
你可以使用add
方法新增元素到集合中:
final drinks = <String>{};
drinks.add('cola');
刪除元素
你可以使用remove
方法刪除元素從集合中:
final drinks = <String>{'cola', 'tea'};
drinks.remove('cola');
合併集合
你可以使用union
方法合併兩個集合:
final set1 = {1, 2, 3};
final set2 = {3, 4, 5};
final unionSet = set1.union(set2);
print(unionSet); // {1, 2, 3, 4, 5}
交集
你可以使用intersection
方法計算兩個集合的交集:
final set1 = {1, 2, 3};
final set2 = {3, 4, 5};
final intersectionSet = set1.intersection(set2);
print(intersectionSet); // {3}
差集
你可以使用difference
方法計算兩個集合的差集:
final set1 = {1, 2, 3};
final set2 = {3, 4, 5};
final differenceSet = set1.difference(set2);
print(differenceSet); // {1, 2}
這些是集合的一些基本操作,你可以使用這些方法來操縱集合。
內容解密:
在這個例子中,我們使用了Set
型別注釋建立了一個空集合,然後使用add
方法新增元素到集合中。接著,我們使用contains
方法檢查集合是否包含某個元素。最後,我們使用union
、intersection
和difference
方法合併、交集和差集兩個集合。
圖表翻譯:
graph LR A[集合] --> B[新增元素] B --> C[刪除元素] C --> D[合併集合] D --> E[交集] E --> F[差集]
這個圖表展示了集合的一些基本操作,包括新增元素、刪除元素、合併集合、交集和差集。
集合的基本操作
集合(Set)是一種不允許重複元素的資料結構。在 Dart 中,集合的基本操作包括新增、移除和檢查元素是否存在。
從技術架構視角來看,Dart 的列表(List)和集合(Set)提供了豐富的功能來管理資料集合。深入剖析 List 的底層實作,可以發現其元素的插入和刪除操作在列表頭部或中部時,需要搬移元素,因此效率較低;相對地,若應用場景涉及頻繁的插入刪除,Linked List 則更具效能優勢。然而,Linked List 的記憶體開銷較大,需要權衡利弊。至於 Set,其不允許重複元素的特性使其在需要快速查詢元素是否存在,或進行集合運算(例如聯集、交集、差集)的場景中表現出色。技術選型時,需根據具體應用場景的效能需求和資料特性做出最佳選擇。對於注重執行效率的應用,例如需要頻繁插入刪除元素的場景,Linked List 或 Set 是更優的選擇;而對於資料量較小,且讀取操作較多的場景,List 則更為簡潔高效。未來,隨著 Dart 語言的發展,預計會出現更多針對不同資料結構的最佳化,進一步提升開發效率。玄貓認為,開發者應深入理解不同資料結構的特性和適用場景,才能寫出高效且穩定的 Dart 程式碼。