相比于 js dart list 最明显的一个特点就是可以是强类型。为了能更好的从前端的视角分析 dart list ,从 dynamic 类型开始解释各个方法。如果你还不熟悉 dynamic 可以先看这里 dart 中的 dynamic)
var list = []; //相当于 var list=<dynamic>[] list[0] = 1; list[1] = 'a' //ok 复制代码
我们可以看到,当类型为 dynamic 时,效果和 js 差不多。不进行类型检查。下面看几个常用方法。
增加元素
增加元素的方法都是修改原数组,返回 void
在末尾增加一个元素
和 js 的 push 效果一样
list.add(1); 复制代码
在末尾增加多个元素
与 js 的 concat 不同, concat 不修改原来的数组,而是返回连接后的数组。
list.addAll([2,3]); 复制代码
在末尾增加多个元素也可以这样写,用 + 操作符看起来更简洁
print([1,2]+[3,4]); // 1,2,3,4 复制代码
在任意位置增加一个元素
var list=[1,'a']; list.insert(0,2); print(list); // [2,1,'a'] 复制代码
在任意位置增加多个元素 insertAll
var list = [1, 'a']; list.insertAll(0, [2, 3]); print(list); // [2,3,1,'a'] 复制代码
删除元素
删除方法都会修改原数组
删除最后一个元素 removeLast
返回被删除的元素,和 js 的 pop 效果一样
list.removeLast(0); 复制代码
在任意位置删除一个元素 removeAt
返回被删除的元素。index 必须在[0,Length)
否则抛异常
list.removeAt(0); 复制代码
根据值删除一个元素 removeAt
成功返回 true,失败返回 false 与 js 不同的是 元素的类型不会自动转换,只能类型和值都相同才会删除成功
var a = ['1', '2', 3, 4]; var isOk = a.remove(1); print(isOk); // false isOk = a.remove('1'); print(isOk); // true 复制代码
删除范围内多个元素 removeRange
返回 void。range 必须在[0,Length)
否则抛异常。被删除的范围含头不含尾
list.removeRange(0,1); 复制代码
根据条件删除元素 removeWhere
返回 void 删除不成功不报错,和 remove 一样,类型和值都匹配的元素才能删除成功
var a = ['1', '2', 1]; a.removeWhere((item) => item == 1); print(a); // [ '1','2'] 复制代码
根据条件保留元素,也就是删除不符合条件的元素 retainWhere
返回 void
list.retainWhere((item) => item>10) 复制代码
删除所有元素
list.clear(); 复制代码
也可以用
list = []; 复制代码
修改一个元素
list[0] = 1; 复制代码
修改多个元素 setAll
返回 void ,修改的长度不能超过数组的长度,否则抛异常。
var a = <int>[1, 4, 5]; a.setAll(1, [2, 3]); print(a); // [ 1,2,3] 复制代码
还有几个方法,但都可以方便用 setAll 替代
- fillRage,
- repalceRage
- setRange
查询元素
查询元素的方法都不修改原数组
查询元素的类型和值都得得相同才算是匹配成功
获得一个元素 elementAt
var n= list.elementAt(0); 复制代码
也可以用
var n = list[0] 复制代码
判断数组中是否含有指定的一个元素 contains
var list=[1] list.contains(1); //true list.contains('1') //false 复制代码
获取指定一个元素在的索引 indexOf
查不到返回 -1
var list=[1,1,2] list.indexOf(1); // 0 list.indexOf(1,1) //false 因为是从位置 1 查找。这个不常用,知道就行 复制代码
获取指定一个元素在的索引,从后向前找 lastIndexOf
查不到返回 -1 和 indexOf 用法一样,只是从后面开始查找
var list=[1,1,2] list.indexOf(1); // 0 list.lastIndexOf(1) // 1 list.lastIndexOf(1,0) // 0 不常用,知道就行 复制代码
根据条件只返回一个符合条件的元素 indexWhere, lastIndexWhere
查不到返回 -1
var list=[1,1,2,2,2,3]; list.indexWhere((item)=>item==2); // 2 list.lastIndexWhere((item)=>item==2); // 4 复制代码
根据条件查询元素 where, firstWhere,lastWhere
返回 iterable 这个是比较常用的方法
var list=[1,1,2,2,2,3]; list.indexWhere((item)=>item==2); // 2 复制代码
firstWhere,lastWhere 可以用 where 替代,只是代码会更简洁一些
var list=[1,1,2,2,2,3]; var nums= list.indexWhere((item)=>item>1); print(nums.first); // 获取第一个元素 print(nums.last); // 获取最后一个元素 复制代码
保证只有一个元素 singleWhere
如果符合条件的元素不是 1
个会抛异常。singleWhere 的意义在于保证 有且只有一个
相当于 我发誓...
single 属性也是一样的,如果元素多于一个,调用这个属性会引发异常
获取范围内多个元素 sublist,getRange,take,takeWhile
var list=[1,2,3,4,5]; var nums= list.sublist(4); print(nums); // 5 nums= list.sublist(0,2); print(nums); // [1,2] nums= list.getRange(0,2); print(nums); // (1,2) 复制代码
sublist,getRange都是返回范围的元素,但是sublist返回的是 List,getRange 返回的 是 iterable
sublist的 第二个索引参数可以为空,getRange第二个索引参数不能为空。从这点看来 getRange 更加名副其实,sublist 更象 js 的 sllice
take是从索引0取指定个数元素 take(3) 相当于 getRange(0,3)
takeWhile 是 从索引 0位置 处开始,获取所有满足条件的元素。
其它常用方法
有的方法和 js 的差不多,就不举例了。
- forEach
- map
- very
- any
- join
还有一个 shuffle 方法是随机打乱原数组的, js 里没有这样的方法,不过 shuffle 基本上也没什么出镜的机会。
快速生产数据 generate
构造函数之一
List<int>.generate(3, (int index) => index * index); // [0, 1, 4] 复制代码
把 Iterable 转成 List 对象 toList
toList还是很常用的。比如 map 函数一般会接一个 toList
[1,2,3].map((item)=>item+1).toList() 复制代码
降低维度 reduce,fold
fold 需要初始值,reduce不需要。
var a = [1, 2, 3, 4]; var c = a.reduce((a, b) => a + b); print(c); // 10 var d = a.fold(1, (a, b) => a + b); print(d); // 1 + (1 + 2 + 3 + 4) 复制代码
扩充 expand
var a = [1, 2]; var c = a.expand(item=>item[item+1,item+1]); print(c); // (2,2,3,3) 复制代码
根据原数组创新一个新数组 of
构造函数之一。 返回 List. 相当于 js 的 list.splice(0)。
var a=[1,2,3]; var b=List.of(a); b.add(4); print(a); //1,2,3 print(b); //1,2,3,4 复制代码
根据 iterable 对象创新一个新数组 from
构造函数之一。和 of 一样返回 List. 和 of 一样都是创建新数组,但来源不同,from的源是 iterable 对象。也就是说 from 可以的 of 可能不可以。
var a=[1,2,3]; var b=List.from(a); b.add(4); print(a); //1,2,3 print(b); //1,2,3,4 //下面的 from 可以 of 不可以 List<dynamic> dynList = ...some JSON value...; List<Map<String, dynamic>> fooList = List.from(dynList.where((x) => x is Map && x["kind"] == "foo")); 复制代码
排序 sort
和 js 一样用法。
var numbers = ['two', 'three', 'four']; // Sort from shortest to longest. numbers.sort((a, b) => a.length.compareTo(b.length)); print(numbers); // [two, four, three] 复制代码
也可以不用 compareTo,只要返回的值是 int 就行,这样就和 js 的写法一样了。
var numbers = ['two', 'three', 'four']; // Sort from shortest to longest. numbers.sort((a, b) => a.length - b.length)); print(numbers); // [two, four, three] 复制代码
查询特定类型的元素 whereType
var a = [1, 'a']; var b = a.whereType<int>(); //不建议这样写 Iterable<String> c = a.whereType(); print(b); // (1) print(c); // (a) 复制代码
虽然示例的两种写法都可以,但是建议 var b = a.whereType<int>();
这种写法。
用 var 声明的类型 dart 会进行类型推断。比自己写类型要好。
获得 List 的视图 cast
如果你知道数据库的视图,这里的视图就不难理解了。就是不创新新的 List,只是生成视图。一个 list 可以生成多个视图。只要图图的类型可以从 原数组的类型转换就可以。一般来说是从子类向父类转
var a=[1,2,3,4]; var c=a.cast<double>(); //生成 double 视图,因为 int 可以转成 double a[0]=c[0].ceil(); //可以调用 doulbe的方法了 c.removeLast(); //操作视图也就是操作原数组 print(c); // 1,2,3 print(a); // 1,2,3 复制代码
转成其它类型
- toSet
- toString
- asMap
如果想对数组数据去重 ,toSet是一个选择。 asMap 要注意是只是生成 map 的视图而已,是让你可以暂时把 list 当作 map 来用。
前面的例子大多是 dynamic的,不验证类型,但如果指明类型,那么就必须是这样的类型。
var list=[1,2,3]; list.add('a');// 错误 复制代码
var list=[1,2,3];
相当于是 var list = <int>[1,2,3];
因为后面的数据都是 int 型,所以dart就认为 list 都应该是 int 型的数据。这时如果想要不考虑类型,需要显示的用 dynamic 指明
var list=<dynamic>[1,2,3]; list.add('a');// 正确 复制代码