列表推导式生成一维数组
列表推导式常见的 3 种形式:
[x for x in data if condition]
这里的 if 主要是起到一个条件判断的作用,data 里面的数据,只有满足 if 的条件才会被留下。[exp1 if condition else exp2 for x in data]
此处if…else主要起赋值作用,当data中的数据满足if条件时将其做exp1处理,否则按照exp2处理,最后统一生成为一个数据列表。[exp1 if condition else exp2 for x in data if condition]
前面 if..else 参考第 2 种形式,后面的 if 参考 第 1 种形式。
列表推导式可以生成元素值都相等的数组。 列表推导式可以使用变量。 列表推导式可以使用 表达式。 列表推导式可以过滤一些元素。 列表推导式可以使用 if-else 做比较复杂的操作
下面的例子中 N = 4
- 生成
nums = [0, 0, 0, 0]
数组。 值都相等nums = [0 for i in range(N)]
相当于:
nums = []
for i in range(N):
nums.append(0)
- 生成
nums=[1, 2, 3, 4]
数组。 使用了一个变量 inums = [i for i in range(1, N+1)]
相当于:
nums = []
for i in range(1, N+1):
nums.append(i)
- 生成
nums=[1, 4, 9, 16]
数组 使用i**2
表达式nums = [i**2 for i in range(1, N+1)]
相当于:
nums = []
for i in range(1, N+1):
nums.append(i**2)
- 生成
nums=[1, 9, 25, 49]
数组。 使用if i % 2
条件判断过滤偶数,并且对奇数平方。nums=[i**2 for i in range(1, N*2) if i % 2]
相当于:
nums = []
for i in range(1, N*2):
if i % 2:
nums.append(i**2)
- 生成
nums=[1, -2, 3, -4]
数组。使用 if-else 将,偶数位取反。nums=[i if i % 2 else -i for i in range(1, N+1)]
相当于
nums = []
for i in range(1, N+1):
if i % 2:
nums.append(i)
else:
nums.append(-i)
- 去掉值为 3 的倍数的数,然后剩下的偶数取反。
nums=[1, -2, -4, 5, 7]
nums=[i if i%2 else -i for i in range(1, 2*N) if i % 3]
相当于:
nums = []
for i in range(1, 2*N):
if i % 3:
if i % 2:
nums.append(i)
else:
nums.append(-i)
以上都是一些生成一维数组的方式。
列表推导式生成多维数组
其实对于 多维数组,我感觉和 一维数组的生成方式没有什么太多的区别,就是再套一层而已。(PS: 突然想起千层饼:禁止套娃。)
- 生成一个
nums = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
数组。nums=[[j for j in range(1, N+1)] for i in range(1, N+1)]
相当于,注意下面 变量 i, j。
nums = []
for i in range(1, N+1):
temp = []
for j in range(1, N+1):
temp.append(j)
nums.append(temp)
这里我给出我写 列表推导式生成二维数组 的步骤。
我会先把 一维也就是子层嵌套的 先写出来, 假设 这一整串代码等于 A
A = [j for j in range(1, N+1)]
然后 我再写 二维的 列表推导式也写出来。
[i for i in range(1, N+1)]
用 第 1 步的 那一整串代码,直接去替换 二维里面的 i。
[[j for j in range(1, N+1)] for i in range(1, N+1)]
如果这个时候我要写三维的列表推导式。 我就把前面生成二维的代码 当成一个整体 B。 B = [[j for j in range(1, N+1)] for i in range(1, N+1)]
再写 三 维的列表推导式 [k for k in range(1, N+1)]
最后把 k 替换成 B
[[[j for j in range(1, N+1)] for i in range(1, N+1)] for k in range(1, N+1)]
列表推导式的使用建议
- 列表推导式生成一个数组会比 使用 for 循环一个个的 append 要快。 所以对于一些简单的列表,最好是使用列表推导式。
- 太复杂的列表推导式,如果要照顾别人的阅读能力,考虑使用for循环嵌套。
至于对我而言,什么是比较复杂的列表推导式呢?
- 三维数组感觉都比较复杂。
- 第3种列表推导式形式。
这也不是说,复杂的列表推导式不需要学或者不应该写。前面说了,太复杂的列表推导式是因为不容易阅读,会增加沟通成本。但是如果,在一个比较复杂的列表推导式旁边再附上 多层循环的等价代码,那不管多么复杂的列表推导式,我觉得都可以接受。毕竟一串代码更多的时候是机器在运行的,那这样的话衡量代码的标准就只有时间复杂度和空间复杂度了。
阅读就是读者理解能力和作者表达能力的相遇。