本次圖片是向 kallehallden 致敬,熱愛程式設計,保持一顆好奇的心
老鐵記得 轉發 ,貓哥會呈現更多 Flutter 好文~~~~
微信 flutter 研修群 ducafecat
貓哥說
最近沒時間錄視訊,一直在做專案和技術研究,就翻譯和寫寫文章和大家分享。
關於這篇文章,我只想說一切讓我們少寫程式碼,讓程式碼簡潔的方式都是好東西!
也許這個元件 dartx 在某些人眼裡不夠成熟,但是這代表了一種思路,你應該去借鑑。
原文
參考
正文
Darts Iterable 和 List 提供了一組基本的方法來修改和查詢集合。然而,來自 c # 背景,它有一個非凡的 LINQ-to-Objects 庫,我覺得我日常使用的一部分功能缺失了。當然,任何任務都可以只使用 dart.core 方法來解決,但有時需要多行解決方案,而且程式碼不是那麼明顯,需要花費精力去理解。我們都知道,開發人員花費大量時間閱讀程式碼,使程式碼簡潔明瞭是至關重要的。
Dartx 包允許開發人員在集合(和其他 Dart 型別)上使用優雅且可讀的單行操作。
下面我們將比較這些任務是如何解決的:
- first / last collection item or null / default value / by condition;
- map / filter / iterate collection items depending on their index;
- converting a collection to a map;
- sorting collections;
- collecting unique items;
- min / max / average by items property;
- filtering out null items;
安裝 dartx pubspec.yaml
dependencies:
dartx: ^0.7.1
複製程式碼
import 'package:dartx/dartx.dart';
複製程式碼
First / last collection item…
… or null
為了得到第一個和最後一個收集專案的簡單省道,你可以這樣寫:
final first = list.first;
final last = list.last;
複製程式碼
如果 list 為空,則丟擲 statereerror,或者顯式返回 null:
final firstOrNull = list.isNotEmpty ? list.first : null;
final lastOrNull = list.isNotEmpty ? list.last : null;
複製程式碼
使用 dartx 可以:
final firstOrNull = list.firstOrNull;
final lastOrNull = list.lastOrNull;
複製程式碼
類似地:
final elementAtOrNull = list.elementAtOrNull(index);
複製程式碼
如果索引超出列表的界限,則返回 null。
… or default value
鑑於你現在記住這一點。第一和。當 list 為空時,last getter 會丟擲錯誤,以獲取第一個和最後一個集合項或預設值,在簡單的 Dart 中,你會寫:
final firstOrDefault = (list.isNotEmpty ? list.first : null) ?? defaultValue;
final lastOrDefault = (list.isNotEmpty ? list.last : null) ?? defaultValue;
複製程式碼
使用 dartx 可以:
final firstOrDefault = list.firstOrDefault(defaultValue);
final lastOrDefault = list.lastOrElse(defaultValue);
複製程式碼
類似於 elementAtOrNull:
final elementAtOrDefault = list.elementAtOrDefault(index, defaultValue);
複製程式碼
如果索引超出列表的邊界,則返回 defaultValue。
… by condition
要獲取第一個和最後一個符合某些條件或 null 的集合項,一個普通的 Dart 實現應該是:
final firstWhere = list.firstWhere((x) => x.matches(condition));
final lastWhere = list.lastWhere((x) => x.matches(condition));
複製程式碼
除非提供 orElse,否則它將為空列表丟擲 StateError:
final firstWhereOrNull = list.firstWhere((x) => x.matches(condition), orElse: () => null);
final lastWhereOrNull = list.lastWhere((x) => x.matches(condition), orElse: () => null);
複製程式碼
使用 dartx 可以:
final firstWhereOrNull = list.firstOrNullWhere((x) => x.matches(condition));
final lastWhereOrNull = list.lastOrNullWhere((x) => x.matches(condition));
複製程式碼
… collection items depending on their index
Map…
當您需要獲得一個新的集合,其中每個專案以某種方式依賴於其索引時,這種情況並不罕見。例如,每個新項都是來自原始集合的項及其索引的字串表示形式。
如果你喜歡我的一句俏皮話,簡單地說就是:
final newList = list.asMap()
.map((index, x) => MapEntry(index, '$index $x'))
.values
.toList();
複製程式碼
使用 dartx 可以:
final newList = list.mapIndexed((index, x) => '$index $x').toList();
複製程式碼
我應用.toList ()是因為這個和大多數其他擴充套件方法返回 lazy Iterable。
Filter...
對於另一個示例,假設只需要收集奇數索引項。使用簡單省道,可以這樣實現:
final oddItems = [];
for (var i = 0; i < list.length; i++) {
if (i.isOdd) {
oddItems.add(list[i]);
}
}
複製程式碼
或者用一行程式碼:
final oddItems = list.asMap()
.entries
.where((entry) => entry.key.isOdd)
.map((entry) => entry.value)
.toList();
複製程式碼
使用 dartx 可以:
final oddItems = list.whereIndexed((x, index) => index.isOdd).toList();
// or
final oddItems = list.whereNotIndexed((x, index) => index.isEven).toList();
複製程式碼
Iterate…
如何記錄集合內容並指定專案索引?
In plain Dart:
for (var i = 0; i < list.length; i++) {
print('$i: ${list[i]}');
}
複製程式碼
使用 dartx 可以:
list.forEachIndexed((element, index) => print('$index: $element'));
複製程式碼
Converting a collection to a map
例如,需要將不同 Person 物件的列表轉換為 Map < String,Person > ,其中鍵是 Person.id,值是完整 Person 例項。
final peopleMap = people.asMap().map((index, person) => MapEntry(person.id, person));
複製程式碼
使用 dartx 可以:
final peopleMap = people.associate((person) => MapEntry(person.id, person));
// or
final peopleMap = people.associateBy((person) => person.id);
複製程式碼
要得到一個 Map,其中鍵是 DateTime,值是列出那天出生的人的名單 < person > ,在簡單的 Dart 中,你可以寫:
final peopleMapByBirthDate = people.fold<Map<DateTime, List<Person>>>(
<DateTime, List<Person>>{},
(map, person) {
if (!map.containsKey(person.birthDate)) {
map[person.birthDate] = <Person>[];
}
map[person.birthDate].add(person);
return map;
},
);
複製程式碼
使用 dartx 可以:
final peopleMapByBirthDate = people.groupBy((person) => person.birthDate);
複製程式碼
Sorting collections
你會怎樣用普通的 dart 來分類一個收集? 你必須記住這一點
list.sort();
複製程式碼
修改源集合,要得到一個新例項,你必須寫:
final orderedList = [...list].sort();
複製程式碼
Dartx 提供了一個擴充套件來獲得一個新的 List 例項:
final orderedList = list.sorted();
// and
final orderedDescendingList = list.sortedDescending();
複製程式碼
如何基於某些屬性對收集項進行排序?
Plain Dart:
final orderedPeople = [...people]
..sort((person1, person2) => person1.birthDate.compareTo(person2.birthDate));
複製程式碼
使用 dartx 可以:
final orderedPeople = people.sortedBy((person) => person.birthDate);
// and
final orderedDescendingPeople = people.sortedByDescending((person) => person.birthDate);
複製程式碼
更進一步,你可以通過多個屬性對集合項進行排序:
final orderedPeopleByAgeAndName = people
.sortedBy((person) => person.birthDate)
.thenBy((person) => person.name);
// and
final orderedDescendingPeopleByAgeAndName = people
.sortedByDescending((person) => person.birthDate)
.thenByDescending((person) => person.name);
複製程式碼
Collecting unique items
要獲得不同的集合項,可以使用以下簡單的 Dart 實現:
final unique = list.toSet().toList();
複製程式碼
這並不保證保持專案順序或提出一個多行的解決方案
使用 dartx 可以:
final unique = list.distinct().toList();
// and
final uniqueFirstNames = people.distinctBy((person) => person.firstName).toList();
複製程式碼
Min / max / average by item property
例如,要查詢一個 min/max 集合項,我們可以對其進行排序,並獲取 first/last 項:
final min = ([...list]..sort()).first;
final max = ([...list]..sort()).last;
複製程式碼
同樣的方法也適用於按項屬性進行排序:
final minAge = (people.map((person) => person.age).toList()..sort()).first;
final maxAge = (people.map((person) => person.age).toList()..sort()).last;
複製程式碼
或:
final youngestPerson =
([...people]..sort((person1, person2) => person1.age.compareTo(person2.age))).first;
final oldestPerson =
([...people]..sort((person1, person2) => person1.age.compareTo(person2.age))).last;
複製程式碼
使用 dartx 可以:
final youngestPerson = people.minBy((person) => person.age);
final oldestPerson = people.maxBy((person) => person.age);
複製程式碼
對於空集合,它將返回 null。
如果收集專案實現了 Comparable,則可以應用不帶選擇器的方法:
final min = list.min();
final max = list.max();
複製程式碼
你也可以很容易地得到平均值:
final average = list.average();
// and
final averageAge = people.averageBy((person) => person.age);
複製程式碼
以及 num 集合或 num 項屬性的總和:
final sum = list.sum();
// and
final totalChildrenCount = people.sumBy((person) => person.childrenCount);
複製程式碼
Filtering out null items
With plain Dart:
final nonNullItems = list.where((x) => x != null).toList();
複製程式碼
使用 dartx 可以:
final nonNullItems = list.whereNotNull().toList();
複製程式碼
More useful extensions
在 dartx 中還有其他有用的擴充套件。這裡我們不會深入討論更多細節,但是我希望命名和程式碼是不言自明的。
joinToString
final report = people.joinToString(
separator: '\n',
transform: (person) => '${person.firstName}_${person.lastName}',
prefix: '<<️',
postfix: '>>',
);
複製程式碼
all (every) / none
final allAreAdults = people.all((person) => person.age >= 18);
final allAreAdults = people.none((person) => person.age < 18);
複製程式碼
first / second / third / fourth collection items
final first = list.first;
final second = list.second;
final third = list.third;
final fourth = list.fourth;
複製程式碼
takeFirst / takeLast
final youngestPeople = people.sortedBy((person) => person.age).takeFirst(5);
final oldestPeople = people.sortedBy((person) => person.age).takeLast(5);
複製程式碼
firstWhile / lastWhile
final orderedPeopleUnder50 = people
.sortedBy((person) => person.age)
.firstWhile((person) => person.age < 50)
.toList();
final orderedPeopleOver50 = people
.sortedBy((person) => person.age)
.lastWhile((person) => person.age >= 50)
.toList();
複製程式碼
總結
Dartx 包包含了許多針對 Iterable、 List 和其他 Dart 型別的擴充套件。探索其功能的最佳方式是瀏覽原始碼。
感謝軟體包作者 Simon Leier 和 Pascal Welsch。
© 貓哥
往期
開源
GetX Quick Start
新聞客戶端
strapi 手冊譯文
微信討論群 ducafecat
系列集合
譯文
開源專案
Dart 程式語言基礎
space.bilibili.com/404904528/c…
Flutter 零基礎入門
space.bilibili.com/404904528/c…
Flutter 實戰從零開始 新聞客戶端
space.bilibili.com/404904528/c…
Flutter 元件開發
space.bilibili.com/404904528/c…
Flutter Bloc
space.bilibili.com/404904528/c…
Flutter Getx4
space.bilibili.com/404904528/c…