在写脚本过程中总能遇到这样的需求:如一个二维列表list1 = [[1, 2, 3], [11, 22, 33]],如何能有效快捷地得到新的二维列表list2 = [[1, 11], [2, 22], [3, 33]]呢?也就是将子列表中相同位置的元素重组,得到新的列表。有以下三种方案,其中第三种很推荐:
1. 正常思路就是双重循环,如下:
- list1, list2 = [[1, 2, 3], [11, 22, 33]], []
- for idx in range(len(list1[0])):
- list2.append([item[idx] for item in list1])
- print(list2) # [[1, 11], [2, 22], [3, 33]]
2. 使用itemgetter配合一层for循环,如下:
- from operator import itemgetter
- list1 = [[1, 2, 3], [11, 22, 33]]
- list2 = [list(map(itemgetter(idx), list1)) for idx in range(len(list1[0]))]
- print(list2) # [[1, 11], [2, 22], [3, 33]]
3. 但由于循环很麻烦,有一种更简单的方法:zip与解包的结合。(我一般使用这种方案) 如果有小伙伴不知道什么是解包,可参考我的这条博客:元组解包_Aaron_neil的博客
- list1 = [[1, 2, 3], [11, 22, 33]]
- list2 = list(zip(*list1))
- print(list2) # [(1, 11), (2, 22), (3, 33)]
【知识补充】
※ map的用法?
map是python的一个内置函数,根据指定函数对序列做映射。函数为map(func, iterable...),func为指定的函数名,iterable...为一个或者多个序列。map函数返回一个迭代器,可以使用 list() 转换成列表。【用例含义:】通过multi_lists函数对lists序列做映射,映射成对其中每个元素都乘10的操作
- def multi_lists(lists):
- return lists * 10
-
- lists = [1, 2, 3, 4, 5]
- ans = list(map(multi_lists, lists))
- print(ans) # [10, 20, 30, 40, 50]
※ itemgetter的用法?
operator模块下的itemgetter函数主要为了获取对象特定维度的数据,其中的参数为维度序号。其中operator.itemgetter()返回的是一个函数,需要调用返回函数,然后再传递值:
- from operator import itemgetter
- list1 = [[1, 2, 3], [11, 22, 33]]
- func = itemgetter(0) # 获取第0维度上的值
- print(func(list1)) # [1, 2, 3]
所以那我们回归到上面的代码,具体的含义我们解析一下:
- list1 = [[1, 2, 3], [11, 22, 33]]
- list2 = [list(map(itemgetter(idx), list1)) for idx in range(len(list1[0]))]
我们简化一下,省略掉外面的for循环,仅使用idx = 0的这种情况进行分析,那上述代码就变成:
- list1 = [[1, 2, 3], [11, 22, 33]]
- list2 = list(map(itemgetter(0), list1))
所以很容易理解,map函数的本质就是遍历输入的列表,对每个元素执行map里函数的内容。那对应到代码里就是遍历list1,对每一个元素也就是[1, 2, 3]和[11, 22, 33]执行itemgetter(0)这个函数,那itemgetter(0)的本质就是获取列表第0个元素的值,所以就整合起来就是:遍历list1中的每个子列表,获取每个子列表的第一个元素,组成新的列表。