集合
集合是一些有共同特征的独立数据项组成的,通过集合,我们可以可以使用相同的调用代码来处理一个集合的所有元素,而不用单独处理每一个单独的项。
集合可以是空的,可以包含许多元素。根据目的,集合可以有不同的结构和实现。dart常见的集合类型:
- List:通过索引读取元素
- Set:包含只能出现一次的元素
- Map:使用键读取元素
可迭代 Iterable
Iterable是一个可被有序访问的元素的集合。Dart中Iterable是抽象类,是不能被实例化的。但是可以通过List、Set创建Iterable。
Iterable<int> iterable = [1,2,3];
print(iterable.toSet()); // {1, 2, 3}
print(iterable.toList()); // [1,2,3]
Iterable与List的不同之处在于,Iterable没有[]操作符,不能使用如下方式读取特定索引的元素:
var value = iterable[0]; //会报错,提示没有[]操作符
您可以改为使用 读取元素elementAt(),它会逐步遍历可迭代对象的元素,直到到达该位置。
Iterable<String> iterable = ['Salad', 'Popcorn', 'Toast'];
String value = iterable.elementAt(0)
print(value) // 'Salad'
for-in 遍历元素
Iterable<String> iterable = ['Salad', 'Popcorn', 'Toast'];
for (var element in iterable) {
print(element);
}
first、last 访问元素
在某些场景下,您希望只访问Iterable的第一个或最后一个元素。
对于Iterable类,不能直接访问元素,因此不能调用Iterable[0]来访问第一个元素。可以通过first访问第一个元素,通过last访问最后一个元素。
提示:访问Iterable的最后一个元素需要遍历所有其他元素,所以last可能会很慢。在空Iterable上使用first或last会导致StateError异常。
Iterable<String> iterable = const ['Salad', 'Popcorn', 'Toast'];
print('The first element is ${iterable.first}');
print('The last element is ${iterable.last}');
firstWhere()
使用firstWhere()来查找满足特定条件的第一个元素。这个方法要求您传递一个函数,如果输入满足某个条件,则返回匹配的第一个元素。如果firstWhere没有找到,并且orElse参数被忽略,则会抛出StateError异常。
bool predicate(String item) {
return item.length > 5;
}
void main() {
const items = ['Salad', 'Popcorn', 'Toast', 'Lasagne'];
var foundItem1 = items.firstWhere((item) => item.length > 5);
print(foundItem1);
var foundItem2 = items.firstWhere(predicate);
print(foundItem2);
///如果找不到值,也可以使用'orrelse'函数
var foundItem3 = items.firstWhere(
(item) => item.length > 10,
orElse: () => 'None!',
);
print(foundItem3);
}
singleWhere()
从Iterable的对象中,获取满足条件的一个元素,但它只期望只有一个元素满足条件。如果超过一个或没有元素满足条件,则会抛StateError。用法与firstWhere一致。
提示:singleWhere()单步执行 Iterable对象直到最后一个元素,如果Iterable无限或包含大量元素,可能会导致异常。
Iterable<int> iterable = [8, 12, 4, 1, 17, 33, 10];
int a = iterable.singleWhere((e) => e > 30);
int b = iterable.singleWhere((e) => e > 10);
int c = iterable.singleWhere((e) => e > 10, orElse: () => -1);
int d = iterable.singleWhere((e) => e > 40, orElse: () => -1);
print(a); // 33
print(b); // 报错
print(c); // 报错
print(d); // -1
where()
如果你想找到满足某个条件的所有元素,您可以使用where()方法来实现。
var evenNumbers = const [1, -2, 3, 42].where((number) => number.isEven);
print(evenNumbers); // [-2, 42]
for (var number in evenNumbers) {
print('$number is even.');
}
if (evenNumbers.any((number) => number.isNegative)) {
print('evenNumbers contains negative numbers.');
}
// 如果没有元素满足函数,则输出为空.
var largeNumbers = evenNumbers.where((number) => number > 1000);
if (largeNumbers.isEmpty) {
print('largeNumbers is empty!');
}
takeWhile()
takeWhile会从Iterable对象中获取所有满足条件的元素,直到不满足时,跳出迭代,返回不满足前的满足条件的元素集合。
如果没有元素满足where()中的函数,则该方法返回一个空的Iterable。与singleWhere()或firstWhere()不同,where()不会抛出StateError异常
const numbers = [1, 3, -2, 0, 4, 5];
var numbersUntilZero = numbers.takeWhile((number) => number != 0);
print('Numbers until 0: $numbersUntilZero'); // Numbers until 0: (1, 3, -2)
print(numbersUntilZero.toList()); // [1, 3, -2]
skipWhile()
skipWhile会从Iterable对象中跳过所有满足条件的元素,直到不满足时,跳出迭代,返回剩余的包含不满足元素集合。
var numbersStartingAtZero = numbers.skipWhile((number) => number != 0);
print('Numbers starting at 0: $numbersStartingAtZero'); // Numbers starting at 0: (0, 4, 5)
条件检查
使用Iterable,有时需要校验集合中的元素是否满足一些条件,可以不使用for-in。\
every()
Dart提供了every方法:
来判断是否所有的元素都满足某个条件。
Iterable<int> iterable = {-1,0,1,2};
bool satisfy = iterable.every((item)=> item > 2); //是否所有元素都满足>2
print(satisfy) // false
any()
Dart提供了any方法:
来判断是否至少有一个元素满足某个条件。
Iterable<int> iterable = {-1,0,1,2};
//是否至少有一个元素满足>=2
bool satisfy = iterable.any((item)=> item >= 2); // true
map()
Iterable对象可以使用map方法,对集合中的每个元素进行操作或替换,最终返回一个新的集合。
var numbersByTwo = const [1, -2, 3, 42].map((number) => number * 2);
print('Numbers: $numbersByTwo'); // Numbers: (2, -4, 6, 84)