map方法也叫映射,也就是把数组里的元素一一映射(转换)为其他的对象,通常是生成一个新的,包含转换后元素的数组,常常出现在根据数组里的数据生成ui使用的weidget这种场景.比如有个包含字符串的数组,可以很方便的将字符串转换成对应的Text用来在ui中显示

1
2
3
4
5
6
7
8
9
10
List<String> names = ["叶全真","古特雷斯","凯瑟琳.泽塔琼斯"];
@override
Widget build(BuildContext context) {
return Column(
children: names.map((_name) {
return Text(_name);
}).toList(),
);
}

这只是简单的转换,但现实中的业务逻辑往往比较复杂,可能需要元素在数组中的索引值,到另一个对应数组中去获取对应的额外数据,这时候map的功能就显无能为力了,因为map并没有提供索引值给我们.不过还是有办法的.

分析一下,我们需要的是一个在数组中的索引值,和对应的元素的值,数据结构应该是这样的(int index,T element),这么一看是不是和Map字典对象很像,而且字典对象也有map映射的方法,功能和数组的map方法相似,可以将字典映射成为另外一个字典.我们先试试Map的map方法

1
2
3
4
5
6
7
8
//创建字典
Map<int,String> nameMap = {0:"叶全真",1:"古特雷斯",2:"凯瑟琳.泽塔琼斯"};
// 先看看原来字典长什么样
print(newNameMap);
// 转换
var newNameMap = nameMap.map((i, element) => MapEntry(i, Text(element)));
// 再看看新字典长什么样
print(newNameMap);

运行结果:
flutter: {0: 叶全真, 1: 古特雷斯, 2: 凯瑟琳.泽塔琼斯}
flutter: {0: Text(“叶全真”), 1: Text(“古特雷斯”), 2: Text(“凯瑟琳.泽塔琼斯”)}

发现已经达到了预期的效果,字典中values的值由字符串全部被映射为了Text对象.如果希望象数组映射结果一样,得到一个可以直接赋值给类似Column的widgets字段的数据,只要直接把values提取出来作为一个数组即可

1
print(newNameMap.values.toList());

运行结果:
flutter: [Text(“叶全真”), Text(“古特雷斯”), Text(“凯瑟琳.泽塔琼斯”)]

看到这估计大家都有疑问了,明明是要解决数组的map问题,怎么说了这么多的Map的map.哈哈哈,在这里大家就可以笑了,因为flutter给我们提供了一个方法,直接就可以把数组转换为字典,就是数组的asMap方法,看这个名字就知道是什么功能了,转换后key就是数组的索引值:),和上面例子中的模型一模一样.
上一个完整的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List<String> dutys = ["演员","联合国秘书长","体操运动员"];
List<String> names = ["叶全真","古特雷斯","凯瑟琳.泽塔琼斯"];
// 定义一个生成Text的fang
Widget createText(int idx) {
return Text("${dutys[idx]}:${names[idx]}");
}
@override
Widget build(BuildContext context) {
var newMap = names.asMap().map((i, _) => MapEntry(i, createText(i))).values.toList();
print(newMap);
return ....
}

运行结果:
flutter: [Text(“演员:叶全真”), Text(“联合国秘书长:古特雷斯”), Text(“体操运动员:凯瑟琳.泽塔琼斯”)]

到这里已经差不多能用了,不过不够舒服,代码又长,我们希望最好是能够直接像数组的map方法一样,直接通过数组对象调用,不过以目前的dart语法来看,这是不可能的,因为dart不支持类的扩展(objc或者swift中叫做分类,gategory).所以我们能做的就是写一个函数,输入数组和map方法,map方法有两个传参数,索引值和元素值,然后返回你需要的映射后的数组.
好人做到底,我就把函数放出来吧,需要的拿去用.

1
2
3
4
5
6
7
8
9
10
/// 数组带索引映射
static List<T> mapWithIndex<T>(List list,T Function(int index, dynamic value) withIndex) {
return list
.asMap()
.map((k, v) {
return MapEntry(k, withIndex(k, v));
})
.values
.toList();
}

原创文章,转载请注明出处,谢谢!