js-数组:https://www.yuque.com/zhuchaoyang/wrif6k/oe5z47
List-API-docs:https://api.dart.dev/stable/2.10.3/dart-core/List-class.html
几乎每种编程语言中最常见的集合可能是 array 或有序的对象集合。 在 Dart 中的 Array 就是 List 对象, 通常称之为 List 。
Dart 中的 List 字面量非常像 JavaScript 中的 array 字面量。
List 类型包含了很多 List 的操作函数。 更多信息参考 泛型 和 集合.
定义常数的List
在 List 字面量之前添加 const 关键字,可以定义 List 类型的编译时常量:
var s1 = const [1, 2, 3];s1.add(4); //报错s1[1] = 1; //报错
声明方式
下面为什么只有 List() ,而不是使用 new List()。 因为在 Dart 2 中,new 关键字是可选的。 有关更多信息,参考 构造函数的使用。
// 声明方式1:字面量var s1 = [1, 2, 3]; //初始就赋值了,限定了长度,限定了类型,只能是intvar s11 = <int>[1, 2, 3];List s12 = <int>[1, 2, 3];List<int> s13 = [1, 2, 3];var s4 = [1, 'a', true]; //初始就赋值了,限定了长度,未限定类型,任意位置可用任意类型替换print(s1); //[1, 2, 3]print(s1 is List); //true// 声明方式2:构造函数var s1 = List(); //不限定长度,不限定类型,可添加任意类型的数据List s2 = List(); // 不限定长度,不限定类型,可添加任意类型的数据List s3 = List(2); //限定了长度为2,越界会报错,不限定类型,可添加任意类型的数据List s4 = List<int>(); //不限定长度,限定了类型,只能是intprint(s3); //[null, null]
类型推断
Dart建议List里面最好放同一种数据类型。有关更多信息,请阅读 类型推断。
无指定泛型
字面量方式,有默认推断
// 默认推断类型为 int,如果添加元素为非int类型,就会报错。var s1 = [1];s1.add(2);// s1.add('a'); //报错// 默认推断类型为 Stringvar s2 = ['a'];s2.add('b');// s2.add(1); //报错
字面量方式,无默认推断。可添加任意类型。
var s3 = [1, 'a'];s3.add({});print(s3); //[1, 'a', {}]var s4 = [];s4.add(1);s4.add('a');print(s4); //[1, 'a']
构造函数方式,无默认推断。可添加任意类型。
var s5 = List();s5.add(1);s5.add('a');print(s5); //[1, 'a']
指定泛型
字面量方式
// 指定类型为 intvar s1 = <int>[1, 2];// List s1 = <int>[1, 2];// List<int> s1 = [1, 2];s1.add(3);s1.add('a'); //报错
构造函数方式
// 指定类型为 intvar s1 = List<int>(); //即:var s1 = new List<int>(); Dart2之后,new关键字可省略// List s1 = List<int>();// List<int> s1 = List();s1.add(3);s1.add('a'); //报错
constructors
filled
https://api.dart.dev/stable/2.10.3/dart-core/List/List.filled.html
使用给定值,填充一个数组。
var s1 = List.filled(3, 1);print(s1); //[1, 1, 1]//如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。var s1 = List.filled(3, []);s1[0].add(1);print(s1); //[[1], [1], [1]]//You can use List.generate to create a list with a new object at each position.var s1 = List.generate(3, (index) => []);s1[0].add(1);print(s1); //[[1], [], []]
growable 创建的数组是否可增长,默认为false
var s1 = List.filled(3, 1, growable: false);print(s1); //[1, 1, 1]s1.add(2); //报错:Cannot add to a fixed-length listvar s1 = List.filled(3, 1, growable: true);print(s1); //[1, 1, 1]s1.add(2);print(s1); //[1, 1, 1, 2]
generate
Generates a list of values.
Creates a list with length positions and fills it with values created by calling generator for each index in the range 0 .. length - 1 in increasing order.
List<int>.generate(3, (int index) => index * index); // [0, 1, 4]
var s2 = List.generate(3, (int index) => index * index);print(s2); //[0, 1, 4]var s3 = List.generate(3, (index) {return index;});print(s3); //[0, 1, 2]
属性
length
Lists 的下标索引从 0 开始,第一个元素的索引是 0。 list.length - 1 是最后一个元素的索引。 访问 List 的长度和元素与 JavaScript 中的用法一样:
var s1 = [1, 2, 3];print(s1.length); //3print(s1[0]); //1 获取指定索引的元素值s1[0] = 5; //修改指定索引的元素值
first、last 返回首位、末位元素
var s1 = [1, 2, 3, 4];print(s1.first); //1print(s1.last); //4
isEmpty、isNotEmpty 是否为空、不为空
var s1 = [];print(s1.isEmpty); //trueprint(s1.isNotEmpty); //false
single
如果数组中有且只有一个元素,返回该元素。
如果数组中没有元素,或者有至少2个元素,就会报错。
var s1 = [];var s2 = [1];var s3 = [1, 2];// print(s1.single); //报错print(s2.single); //1print(s3.single); //报错
reversed 倒置
返回一个List的倒序排列的 Iterable 。原数组不变
var s1 = [1, 2, 3];print(s1.reversed); //(3, 2, 1)
hashCode
返回此对象的哈希码。
var s1 = [1, 2, 3];print(s1.hashCode); //480963117
Iterable
方法
转换
toString
var s1 = [1, 2, 3];print(s1.toString()); //"[3, 2, 1]"
toList
Creates a List containing the elements of this Iterable.
The elements are in iteration order. The list is fixed-length if growable is false.
var s1 = [1, 2, 3];var s2 = s1.reversed;print(s2); //Iterable (3, 2, 1)print(s2.toList()); //[3, 2, 1]
toSet
将List转为Set,并去除后面重复的元素。原数组不变
var s1 = [1, 2, 3, 2, 1];print(s1.toSet()); //Set {1, 2, 3}
应用:list去重
var s1 = [1, 2, 3, 1, 5, 2];print(s1.toSet().toList()); //[1, 2, 3, 5]var s2 = Set();s2.addAll(s1);print(s2); //[1, 2, 3, 5]
asMap
将list转为map。原数组不变
var s1 = ['a', 'b'];print(s1.asMap()); //Map {0: 'a', 1: 'b'}
join 连接
把数组转换为字符串,可以设置每一项之间的连接符,返回转换的字符串。原数组不变
var s1 = [1, 2, 3];print(s1.join()); //"123" 注意:不传参数的时候,js默认为逗号隔开;dart默认就是没有分隔符print(s1.join(',')); //"1,2,3"
增删改
add、addAll 添加元素
add(element) 添加一个元素到 List 末尾。addAll(List) 添加一个 List 到 List 末尾。
// add(element) 添加一个元素到 List 末尾var s1 = [1, 2];s1.add(3);print(s1); //[1, 2, 3]// addAll(List) 添加一个 List 到 List 末尾。var s2 = [1, 2];s2.addAll([4, 5]);print(s2); //[1, 2, 4, 5]
insert、insertAll 指定插入
insert(index, element) 在指定的index处插入元素,其余顺延。insertAll(index, List) 在指定的index处插入 List,其余顺延。(合并两个 List )
// insert(index, elememt) 在指定的index处插入元素var s3 = [0, 1, 2, 3, 4, 5];s3.insert(1, 4);print(s3); //[0, 4, 1, 2, 3, 4, 5]//insert(index, List) 在指定的index处插入 Listvar s4 = [0, 1, 2, 3, 4, 5];s4.insertAll(1, [10, 20]);print(s4); //[0, 10, 20, 1, 2, 3, 4, 5]
remove、removeAt、removeLast、removeRange、removeWhere 删除元素
remove(obj) 删除具体的元素。如果有找到,返回 true 。removeAt(index) 删除指定索引的元素,返回删除的元素。removeLast() 删除末尾元素,返回删除的元素。removeRange(start, end) 删除指定范围内的元素,含头不含尾。removeWhere((item) => item > 2) 根据参数(函数)的返回条件,进行筛选。
// remove(element) 删除具体的元素List s1 = [1, 3, 5, 7];print(s1.remove(3)); //trueprint(s1); //[1, 5, 7]// removeAt(index) 删除指定索引的元素List s2 = [1, 3, 5, 7];print(s2.removeAt(1)); //3print(s2); //[1, 5, 7]// removeLast() 删除末尾元素List s3 = [1, 3, 5, 7];print(s3.removeLast()); //7print(s3); //[1, 3, 5]// removeRange(start, end) 删除指定范围内的元素,含头不含尾。List s4 = [1, 3, 5, 7];s4.removeRange(0, 2);print(s4); //[5, 7]// removeWhere((item) => item > 2) 根据参数(函数)的返回条件,进行筛选。List s5 = [1, 3, 5, 7];s5.removeWhere((item) => item > 3);// 等同于// s5.removeWhere((item) {// return item > 3;// });print(s5); //[1, 3]
clear() 清除所有元素
var s1 = [1, 2, 3, 4];s1.clear();print(s1); //[]
retainWhere 保留
按条件保留,无返回。
var s1 = [1, 2, 3, 4];s1.retainWhere((item) => item > 2);print(s1); //[3, 4]
setRange、replaceRange、fillRange 修改元素
setRange(start, end, List) 范围修改,含头不含尾,无返回。replaceRange(start, end, List) 范围替换,含头不含尾,无返回(类似js的 splice)。fillRange(start, end, element) 用指定的值替换范围内的值,含头不含尾,无返回。
// setRange(start, end, List) 范围修改List s1 = [0, 1, 2, 3, 4, 5];List s2 = [11, 13, 15, 17, 19];// 从s2取出 0 1 2 位置的值,修改s1对应 0 1 2 位置的值s1.setRange(0, 3, s2); //[11, 13, 15, 3, 4, 5]// s1.setRange(3, 3, s2); //[0, 1, 2, 3, 4, 5] start和end相同,则不变。// s1.setRange(3, 10, s2); //start和end任何一个超出s1 s2的角标 则报错。print(s1);
// replaceRange(start, end, List) 范围替换List s1 = [0, 1, 2, 3, 4, 5];List s2 = [11, 13, 15, 17, 19];s1.replaceRange(0, 3, s2); //[11, 13, 15, 17, 19, 3, 4, 5]// s1.replaceRange(3, 3, s2); //[0, 1, 2, 11, 13, 15, 17, 19, 3, 4, 5]// s1.replaceRange(3, 10, s2); //start和end任何一个超出s1 s2的角标,则报错。print(s1);
// fillRange(start, end, element) 用指定的值替换范围内的值List s1 = [0, 1, 2, 3, 4, 5];List s2 = [99];s1.fillRange(0, 3, s2); //[[99], [99], [99], 3, 4, 5]// s1.fillRange(3, 3, s2); //[0, 1, 2, 3, 4, 5]// s1.fillRange(3, 10, s2); //start和end任何一个超出s1 s2的角标,则报错。print(s1);
setAll
setAll(index, List) 从index开始,使用List内的元素逐个替换本 List 中的元素。
var s1 = [0, 1, 2, 3, 4, 5];s1.setAll(2, [10, 11]);print(s1); //[0, 1, 10, 11, 4, 5]
查找、获取
elementAt 获取指定索引的元素
elementAt(index) 获取指定索引位置的元素。
var s1 = [1, 2, 3, 4];print(s1.elementAt(1)); //2print(s1[1]); //2
indexOf、lastIndexOf
往前、后查找当前值在数组中第一次出现的位置索引。原数组不变返回**:索引,没有找到返回 -1
- 第一个参数:要查找的值
- 第二个参数:开始查找的索引,默认从索引 0 开始查找。indexOf、lastIndexOf 会从索引位置开始往前、后查找。 ```dart var s1 = [1, 2, 3, 4, 3, 2]; print(s1.indexOf(3)); //2 print(s1.indexOf(3, 3)); //4
print(s1.lastIndexOf(3)); //4 print(s1.lastIndexOf(3, 1)); //-1
<a name="uYxv4"></a>### contains 是否含有指定元素`contains(obj)` 返回布尔值,表示是否找到了指定元素```dartvar s1 = [1, 2, 3, 4];print(s1.contains(2)); //true
firstWhere、lastWhere
firstWhere((e)=>(bool)) 返回第一个满足条件的元素(不是元素的index)lastWhere((e)=>(bool)) 从后往前找,返回第一个满足条件的元素的值(不是index)
var s1 = [1, 3, 5, 7];print(s1.firstWhere((item) => item > 2)); //3print(s1.lastWhere((item) => item > 2)); //7// 返回满足条件的第一个元素,不满足 报错// print(s1.firstWhere((item) => item > 8)); //不满足,报错// 返回满足条件的第一个元素,不满足 返回orElse方法的返回值print(s1.firstWhere((item) => item > 8, orElse: () => (10))); //10
indexWhere、lastIndexWhere
indexWhere((e)=>(bool)) 返回第一个满足条件的元素的indexlastIndexWhere((e)=>(bool)) 从后向前找 返回第一个满足条件的元素的index
var s1 = [1, 3, 5, 7];print(s1.indexWhere((item) => item > 2)); //1print(s1.lastIndexWhere((index) => index > 2)); //3//返回第一个满足条件的元素的index 不存在则返回-1print(s1.indexWhere((item) => item > 10)); //-1//返回第一个满足条件的元素的index,从index为2开始寻找print(s1.indexWhere((item) => item > 3, 2)); //2print(s1.indexWhere((item) => item > 10, 2)); //-1
sublist、getRange 获取指定范围内元素
sublist(start,[end]) 从指定index 截取list,返回 List。原数组不变getRange(start,end) 从list中截取start-end范围内的数据,返回 Iterable。原数组不变
// sublist(start, [end]) end可选var s1 = [0, 1, 2, 3, 4, 5];print(s1.sublist(1)); //[1, 2, 3, 4, 5]print(s1.sublist(1, 3)); //[1, 2]// print(s1.sublist(-1)); //报错// getRange(start, end)var s2 = [0, 1, 2, 3, 4, 5];// print(s2.getRange(1)); //报错print(s2.getRange(1, 3)); //Iterable (1, 2)
take、takeWhile 获取元素
take(count) 从0开始取count个元素,并以 Iterable 形式返回。原数组不变skipWhile((item) => (bool)) 从0开始取,直至第一个不符合函数的元素,将其前面的元素以 Iterable 形式返回。原数组不变
// take(count)var s1 = [1, 2, 3, 4, 5];print(s1.take(2)); //Iterable (1, 2)// takeWhere((item) => (bool))var s2 = [1, 2, 3, 4, 5];print(s2.takeWhile((item) => (item < 3))); //Iterable (1, 2)
skip、skipWhile 反选元素
skip(count) 越过count个元素后,然后将其之后的元素以 Iterable 形式返回。原数组不变skipWhile((item) => (bool)) 找到第一个不符合条件的元素,然后将其及其之后的元素以 Iterable 形式返回。原数组不变
// skip(count)var s1 = [1, 2, 3, 4, 5];print(s1.skip(2)); //Iterable (3, 4, 5)// skipWhere((item) => (bool))var s2 = [1, 2, 3, 4, 5];print(s2.skipWhile((item) => (item < 3))); //Iterable (3, 4, 5)
排序
sort 自定义排序
对数组元素进行排序。返回排序后的数组。原数组改变
不传参数
将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符Uniode编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(toString() 方法),以便进行比较。
var a1 = ['George', 'John', 'Thomas', 'James', 'Adrew', 'Martin'];a1.sort();print(a1); //[Adrew, George, James, John, Martin, Thomas]//js:基于 sort 本身的排序方法,数字不会按照我们预想的排序var a2 = [1, 19, 2, 24];a2.sort();print(a2); //[1, 2, 19, 24]//dart没有这个问题var a2 = [1, 19, 2, 24];a2.sort();print(a2); //[1, 2, 19, 24]
传递参数(比较函数)
该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。
以升序为例,比较函数应该具有两个参数 a 和 b,其返回值如下:
- 若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
- 若 a 等于 b,则返回 0。
- 若 a 大于 b,在排序后的数组中 a 应该出现在 b 之后,则返回一个大于 0 的值。
var s1 = [1, 19, 2, 24];// 升序s1.sort((a, b) => a - b);// s1.sort((a, b) => a < b ? -1 : 1);print(s1); //[1, 2, 19, 24]// 降序s1.sort((a, b) => b - a);// s1.sort((a, b) => a < b ? 1 : -1);print(s1); //[24, 19, 2, 1]
shuffle 随机重排数组
List内元素,重新随机排列。原数组改变
var s1 = [1, 2, 3, 4, 5];s1.shuffle();print(s1); //[4, 5, 2, 1, 3]
数组的遍历
for 循环
var s1 = [1, 2, 3];for (var i = 0; i < s1.length; i++) {print(s1[i]); //依次输出 1 2 3}
for…in
var s1 = [1, 2, 3];for (var v in s1) {print(v); //依次输出 1 2 3}
forEach
用于调用数组的每个元素,并将元素传递给回调函数。
var s1 = [1, 2, 3];s1.forEach((item) {//遍历每个元素 此时不可add或remove 否则报错 但可以修改元素值,s1[0] = 10;});print(s1); //[10, 2, 3]
map
遍历现有List的每个元素,并做处理,返回一个新的Iterable。原数组不变
var s1 = [0, 1, 2, 3, 4, 5];var s2 = s1.map((item) => item * 2);print(s2); //Iterable (0, 2, 4, 6, 8, 10)print(s1); //List [0, 1, 2, 3, 4, 5]Iterable<bool> s3 = s1.map((item) => item > 2);print(s3); //Iterable (false, false, false, true, true, true)
any、every
any用于检测数组中是否有任意一个元素满足指定条件。不改变原数组every用于检测数组中所有元素是否都符合指定条件。不改变原数组
```dart var s1 = [1, 2, 3]; print(s1.any((item) => item > 2)); //true print(s1.any((item) => item > 4)); //false
print(s1.every((item) => item > 0)); //true print(s1.every((item) => item > 2)); //false
<a name="0JS6D"></a>### where、whereType、singleWhere 筛选元素`where((e)=>(bool)` 根据指定参数函数筛选每个元素,符合条件的元素组成一个新的Iterable集合。**原数组不变**<br />`whereType()` 从无指定泛型的List中,筛选出指定类型的数据,组成一个新的Iterable集合。**原数组不变**<br />`singleWhere((e)=>(bool>)` 找到那唯一满足条件的元素。**原数组不变**```dart// where((e) => (bool)) 根据条件,筛选元素var s1 = [1, 2, 3, 4, 5];print(s1.where((item) => item > 2)); //Iterable (3, 4, 5)// whereType() 根据数据类型,筛选元素List s2 = [3, 4, "a", true, "b", 5, false];Iterable<int> s21 = s2.whereType(); //筛选出int类型的元素print(s21); //Iterable (3, 4, 5)//singleWhere 根据条件,筛选唯一元素var s3 = [1, 2, 3, 4, 5];print(s3.singleWhere((item) => item == 2)); //2// 找到那唯一满足条件的元素,如果没有满足条件的元素或有多个元素满足条件,// 就返回orElse方法的返回值,如果没有传入orElse则报错。print(s3.singleWhere((item) => item > 10)); //报错print(s3.singleWhere((item) => item > 10, orElse: () => 40)); //2
expand 扩展
根据现有的List,指定一个规则,生成一个新的Iterable集合。原数组不变
var s1 = [1, 2, 3];print(s1.expand((e) => ([e + 1, e + 2]))); //Iterator (2, 3, 3, 4, 4, 5)print(s1); //[1, 2, 3]
递归
reduce
reduce((a, b) => (操作)) 用指定的方法对数组元素做连续操作,返回结果。原数组不变
var s1 = [1, 2, 3, 4, 5];print(s1.reduce((a, b) => a + b)); //15 1+2+3+4+5print(s1.reduce((a, b) => a * b)); //120 1*2*3*4*5print(s1); //[1, 2, 3, 4, 5]
fold
fold(initValue, (preValue, element) => (操作)) 类似js的reduce第2个参数传递了初始值。
根据现有的List和给定的initValue,指定一个参数函数规则,对List每个元素做操作,并将结果返回。
var s1 = [1, 2, 3, 4, 5];var s2 = s1.fold(2, (a, element) => (a + element)); //17 2+1+2+3+4+5print(s2); //[1, 2, 3, 4, 5]print(s1); //[1, 2, 3, 4, 5]
cast 将List的泛型提升到其父祖类
List<String> s1 = ['aaa', 'bbb', 'ccc'];List<Object> s2 = s1.cast(); //类型提升,s2现在类型提升为s1的类型,即 List<String>s2.add('1'); //必须添加同类型的元素 如果 s2.add(1) 就会报错print(s2); //['aaa', 'bbb', 'ccc', '1'];
