相比于 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');// 正确