纪念那些年Python遇到的坑。。。
1. remove 列表元素
var = ['a','b','c','d','e']
for col in var:
print('{0} is processing.'.format(col))
var.remove(col)
Result:
a is processing.
c is processing.
e is processing.
Trick:
如上结果可以看出,莫名其妙把 b 和 d 的两条结果给删除了。究其原因是因为list在remover element之后,index并不会跟着改变。因此会跳过 b 和 d。
improve:
var = ['a','b','c','d','e']
for col in var[:]:
print('{0} is processing.'.format(col))
var.remove(col)
Result:
a is processing.
b is processing.
c is processing.
d is processing.
e is processing.
2. 高效处理二维数组
两个数组的快速操作。
vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
[x * y for x in vec1 for y in vec2]
Result:
[8, 6, -18, 16, 12, -36, 24, 18, -54]
一个矩阵的快速转置操作,当然你可以用numpy的matrix.T来完成。
matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
[[row[i] for row in matrix] for i in range(len(matrix[0]))]
Result:
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
3. reduce实现连乘
阶乘或者连乘的极简实现:
import functools as f
f.reduce(lambda x , y : x * y , range(1,4),2)
Result:(2位初始化因子(也可以不设置),range是[1,2,3] 的列表,实现过程:2*1*2*3)
12
4. convert list to string
将列表转化为字符串:
l = ['我','喜','欢','你','!']
print(str(l))
print(''.join(l))
Result:Obviously,第二条 print 是我们需要的
[‘我’, ‘喜’, ‘欢’, ‘你’, ‘!’]
我喜欢你!
5. 批量 modify 文件名称
批量将文件名称中的 ’ ‘(空格) 替换成 ‘_’
import os
def modify_filename(path):
for p in os.listdir(path): #某路径下的全部文件,包括目录
p = os.path.join(path, p) #路径(dirname)和文件名(basename)的拼接(/)
if os.path.isdir(p): #判断是否为文件夹
modify_filename(p)
else:
#os.path.dirname(path)/os.path.basename():路径信息,文件名信息
os.rename(p, os.path.join(os.path.dirname(p), os.path.basename(p).replace(' ', '_')))
Result:
modify_filename('E:\\test')
6. 嵌套列表 to 单列表
将嵌套列表转化为单列表:
a = [[],[],[],['a'],['b'],['c']]
print(a)
b = sum(a,[])
print(b)
Result:
[[], [], [], [‘a’], [‘b’], [‘c’]]
[‘a’, ‘b’, ‘c’]
7. 嵌套列表 calc the number of element
计算嵌套列表中的元素个数:
import functools as ft ,operator as op
A = [[1,3,5], [2, 3], [4, 5, 6]]
ft.reduce(op.add,map(len,A))
Result:(map/reduce的思想很重要,打好基础以备战Scala)
8
8. if-else with np.where
目标:
处理2组数组
True and True = 0
True and False = 1
False and True = 2
False and False = 3
方法一:最传统的if-else
import numpy as np
cond1 = np.array([True,True,False,False])
cond2 = np.array([True,False,True,False])
result = []
for i in range(4):
if (cond1[i] & cond2[i]): result.append(0);
elif (cond1[i]): result.append(1);
elif (cond2[i]): result.append(2);
else : result.append(3);
print(result)
Result:
[0, 1, 2, 3]
方法二:使用where进行截断或者判断处理
import numpy as np
cond1 = np.array([True,True,False,False])
cond2 = np.array([True,False,True,False])
result = []
result = np.where(cond1 & cond2,0,np.where(cond1,1,np.where(cond2,2,3)))
print(result)
Result:
[0 1 2 3]
方法三:好像跟where没有关系,完全是按照逻辑以及 ‘~’ 来的
import numpy as np
cond1 = np.array([True,True,False,False])
cond2 = np.array([True,False,True,False])
result = 1*(cond1 & ~cond2)+2*(cond2 & ~cond1)+3*(~(cond1 | cond2))
print(result)
Result:
[0 1 2 3]
bty,np.where(conditions) 也可以对matrix进行操作哦,比如:
x = np.arange(16).reshape(-1,4);print(np.where(x>5))
返回的结果为:
(array([1, 1, 2, 2, 2, 2, 3, 3, 3, 3], dtype=int64), array([2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int64))
注意这里第一个array是一维(行)的坐标,第二个是二维(列)的坐标。
9. 桶排序(从大到小)
代码如下:
x = list(str(input()).split(','))#输入以逗号分隔
y = int(input())#最大区间数
#输入x:4,45,5,76,13,24,4,56
#输出y:100 即为 可以任意输入0-100区间的数字
bucket = [0 for i in range(y+1)]#初始化桶
for i in range(len(x)) :
bucket[int(x[i])] += 1 #装通
[i for i in range(y-1,-1,-1) for j in range(1,bucket[i]+1)]
Result:时间复杂度是O(M + N),缺点:1.浪费空间 2.无法对小数进行排序
[76, 56, 45, 24, 13, 5, 4, 4]
10. 冒泡排序(从小到大)
代码如下:
x = list(str(input()).split(','))#输入以逗号分隔
for index, item in enumerate(x):#转化为数值类型
x[index] = int(item)
#输入x:4,45,5,76,13,24,4,56
print('before sort:{0}'.format(x))
for i in range(len(x))[::-1]:
for j in range(i):
if int(x[j]) > x[j+1]:
x[j],x[j+1] = x[j+1],x[j]
print('after sort:{0}'.format(x))
Result:时间复杂度是O(N^2),复杂度太高,数据量大很低效
before sort:[4, 45, 5, 76, 13, 24, 4, 56]
after sort:[4, 4, 5, 13, 24, 45, 56, 76]
11. 快速排序(从小到大)
代码如下:
x = list(str(input()).split(','))#输入以逗号分隔
for index, item in enumerate(x):#转化为数值类型
x[index] = int(item)
#输入x:4,45,5,76,13,24,4,56
print('before sort:{0}'.format(x))
def quickSort(seq):
if seq == []:
return []
else:
p = seq[0]
less = quickSort([i for i in seq[1:] if i <= p])
greater = quickSort([i for i in seq[1:] if i > p])
return less + [p] + greater
print('after sort:{0}'.format(quickSort(x)))
Result:时间复杂度最坏是O(N^2),平均复杂度为O(NlogN)
before sort:[4, 45, 5, 76, 13, 24, 4, 56]
after sort:[4, 4, 5, 13, 24, 45, 56, 76]
12. 字符串反转的两种方法
代码如下:
print(''.join(reversed('abcdefg')))
print('abcdefg'[::-1])
Result:
‘gfedcba’
‘gfedcba’
13. 正则匹配的常用两种方法
代码如下:
import re
allFeatures = ['var1','var2','var3','var12','var14','other1','label']
#第一种写法
allFeatures1 = sum([re.findall('^var\d+',str(col)) for col in allFeatures],[])
#第二种写法
allFeatures2 = [col for col in allFeatures if re.match('^var\d+',str(col))] # return is not None
Result:两种方法输出的结果是一样的
[‘var1’, ‘var2’, ‘var3’, ‘var12’, ‘var14’]
13. 字符串替换,正则的使用
需求:给定 ‘ABC_BIN_ENCODING_BIN’,想将最后的 ‘_BIN’ 替换成空。
代码如下:
#当字符串中间没有出现需要被替换的字符串时,此方法可用,反之则不可用。
'ABC_BIN_ENCODING_BIN'.replace('_BIN','')
#输出结果为'ABC_ENCODING'
另外一种方法:
import re
re.compile('_BIN$').sub('','ABC_BIN_ENCODING_BIN')
#输出结果为:'ABC_BIN_ENCODING'
14. groupby().agg()的使用
代码如下:
functions=['count','mean','max']
df.groupby('var2').agg({'var1':functions})
#max,sum
df.groupby('var2').agg({'var1': np.max, 'var3': np.sum})
#count(distinct *)
df.groupby('var2').agg({'var1':pd.Series.nunique})
15. 全局top
代码如下:
df.nlargest(3,columns=['var1'])
16. 分组top
mysql采用自关联的方式来做分组top,代码如下:
select a.sex, a.tip
from tips_tb a
where (
select count(*)
from tips_tb b
where b.sex = a.sex and b.tip > a.tip
) < 2
order by a.sex, a.tip desc;
用python实现以上代码:
# 1.
df.assign(rn=df.sort_values(['total_bill'], ascending=False)
.groupby('sex')
.cumcount()+1)\
.query('rn < 3')\
.sort_values(['sex', 'rn'])
# 2.
df.assign(rn=df.groupby('sex')['total_bill']
.rank(method='first', ascending=False)) \
.query('rn < 3') \
.sort_values(['sex', 'rn'])
17. eval()函数
代码如下:
print(eval("{1: 'a', 2: 'b'}"))
output : {1: ‘a’, 2: ‘b’}