0%

对Counter中的内容进行排序

1
2
3
4
5
6
7
8
9
10
11
12
13
from collections import Counter

x = Counter({'a':5, 'b':3, 'c':7})

# 1
x.most_common() # [('c', 7), ('a', 5), ('b', 3)]

# 2
sorted(x, key=x.get, reverse=True) # ['c', 'a', 'b']

# 3
sorted(x.items(), key=lambda pair: pair[1], reverse=True) # [('c', 7), ('a', 5), ('b', 3)]

一共三种方法,其中第二种方法中传入key=x.get最终返回的是所有的key,而其他两种方法返回的都是排完序之后的list

全角与半角转换在处理汉语语料中会经常出现,这里分别说明汉字、数字、字母的unicode编码范围。以及全角与半角的转换方法。最后给出wiki上全角和半角的编码对照表。这里Python需要用Python3版本。

汉字的判断

汉字的unicode编码范围 u4e00 到 u9fa5。

1
2
3
4
5
6
def is_chinese(uchar):
"""判断一个unicode是否是汉字"""
if uchar >= u'\u4e00' and uchar<=u'\u9fa5':
return True
else:
return False

数字0-9的判断

数字的unicode编码范围根据全角和半角,有两个不同区域,半角数字 u0030 到 u0039,全角数字 uff10 到 uff19。

1
2
3
4
5
6
7
8
9
10
11
12
13
def is_number(uchar):
"""判断一个unicode是否是半角数字"""
if uchar >= u'\u0030' and uchar<=u'\u0039':
return True
else:
return False

def is_Qnumber(uchar):
"""判断一个unicode是否是全角数字"""
if uchar >= u'\uff10' and uchar <= u'\uff19':
return True
else:
return False

大小写字母判断

字母的unicode编码根据字母大小写,以及全角和半角共有四个区域。 半角大写字母:u0041 - u005a ,半角小写字母:u0061 - u007a ; 全角大写字母:uff21 - uff3a , 全角小写字母:uff41 - uff5a 。

1
2
3
4
5
6
7
8
9
10
11
12
13
def is_alphabet(uchar):
"""判断一个unicode是否是半角英文字母"""
if (uchar >= u'\u0041' and uchar <= u'\u005a') or (uchar >= u'\u0061' and uchar <= u'\u007a'):
return True
else:
return False

def is_Qalphabet(uchar):
"""判断一个unicode是否是全角英文字母"""
if (uchar >= u'\uff21' and uchar <= u'\uff3a') or (uchar >= u'\uff41' and uchar <= u'\uff5a'):
return True
else:
return False

非汉字和数字字母的判断

判断除汉字、数字0-9、字母之外的字符。

1
2
3
4
5
6
def is_other(uchar):
"""判断是否非汉字,数字和英文字符"""
if not (is_chinese(uchar) or is_number(uchar) or is_alphabet(uchar)):
return True
else:
return False

全角和半角的转换

全角半角转换需要用到上面的数字、字母等判断。

  1. 所有半角转全角,不是半角范围直接返回,空格半角特殊单独处理,其它半角和全角对应公式:半角 = 全角 - 0xfee0
1
2
3
4
5
6
7
8
9
10
def B2Q(uchar):
"""单个字符 半角转全角"""
inside_code = ord(uchar)
if inside_code < 0x0020 or inside_code > 0x7e: # 不是半角字符就返回原来的字符
return uchar
if inside_code == 0x0020: # 除了空格其他的全角半角的公式为: 半角 = 全角 - 0xfee0
inside_code = 0x3000
else:
inside_code += 0xfee0
return chr(inside_code)
  1. 所有全角转半角,和前面正好相反,公式对应:全角 = 半角 + 0xfee0
1
2
3
4
5
6
7
8
9
10
def Q2B(uchar):
"""单个字符 全角转半角"""
inside_code = ord(uchar)
if inside_code == 0x3000:
inside_code = 0x0020
else:
inside_code -= 0xfee0
if inside_code < 0x0020 or inside_code > 0x7e: #转完之后不是半角字符返回原来的字符
return uchar
return chr(inside_code)
  1. 把整个字符串全角转半角,也可以只转部分如数字和字母
1
2
3
4
5
6
7
def stringQ2B(ustring):
"""把字符串全角转半角"""
return "".join([Q2B(uchar) for uchar in ustring])

def stringpartQ2B(ustring):
"""把字符串中数字和字母全角转半角"""
return "".join([Q2B(uchar) if is_Qnumber(uchar) or is_Qalphabet(uchar) else uchar for uchar in ustring])

测试上面的全角半角转换。

1
2
3
4
5
6
7
text = "电影《2012》讲述了2012年12月21日的世界末日,主人公Jack以及世界各国人民挣扎求生的经历,灾难面前,尽现人间百态。"

print("text原文:", text, sep="\n", end="\n")
text1 = stringQ2B(text)
print("全角转半角:", text1, sep="\n", end="\n")
text2 = stringpartQ2B(text)
print("数字字母全角转半角:", text2, sep="\n", end="\n")

结果如下,只转数字字母与全部转是有区别的:

img

全角半角转换结果

附全角和半角编码对应表

  1. ASCII内字符的全角和半角,包括数字0-9、大小写字母、标点符号等。
ASCII 全角字符 Unicode 半角字符 Unicode
0x20 " " U+3000 " " U+0020
0x21 U+FF01 ! U+0021
0x22 U+FF02 " U+0022
0x23 U+FF03 # U+0023
0x24 U+FF04 $ U+0024
0x25 U+FF05 % U+0025
0x26 U+FF06 & U+0026
0x27 U+FF07 ' U+0027
0x28 U+FF08 ( U+0028
0x29 U+FF09 ) U+0029
0x2A U+FF0A * U+002A
0x2B U+FF0B + U+002B
0x2C U+FF0C , U+002C
0x2D U+FF0D - U+002D
0x2E U+FF0E . U+002E
0x2F U+FF0F / U+002F
0x30 U+FF10 0 U+0030
0x31 U+FF11 1 U+0031
0x32 U+FF12 2 U+0032
0x33 U+FF13 3 U+0033
0x34 U+FF14 4 U+0034
0x35 U+FF15 5 U+0035
0x36 U+FF16 6 U+0036
0x37 U+FF17 7 U+0037
0x38 U+FF18 8 U+0038
0x39 U+FF19 9 U+0039
0x3A U+FF1A : U+003A
0x3B U+FF1B ; U+003B
0x3C U+FF1C < U+003C
0x3D U+FF1D = U+003D
0x3E U+FF1E > U+003E
0x3F U+FF1F ? U+003F
0x40 U+FF20 @ U+0040
0x41 U+FF21 A U+0041
0x42 U+FF22 B U+0042
0x43 U+FF23 C U+0043
0x44 U+FF24 D U+0044
0x45 U+FF25 E U+0045
0x46 U+FF26 F U+0046
0x47 U+FF27 G U+0047
0x48 U+FF28 H U+0048
0x49 U+FF29 I U+0049
0x4A U+FF2A J U+004A
0x4B U+FF2B K U+004B
0x4C U+FF2C L U+004C
0x4D U+FF2D M U+004D
0x4E U+FF2E N U+004E
0x4F U+FF2F O U+004F
0x50 U+FF30 P U+0050
0x51 U+FF31 Q U+0051
0x52 U+FF32 R U+0052
0x53 U+FF33 S U+0053
0x54 U+FF34 T U+0054
0x55 U+FF35 U U+0055
0x56 U+FF36 V U+0056
0x57 U+FF37 W U+0057
0x58 U+FF38 X U+0058
0x59 U+FF39 Y U+0059
0x5A U+FF3A Z U+005A
0x5B U+FF3B [ U+005B
0x5C U+FF3C \ U+005C
0x5D U+FF3D ] U+005D
0x5E U+FF3E ^ U+005E
0x5F _ U+FF3F _ U+005F
0x60 U+FF40 ` U+0060
0x61 U+FF41 a U+0061
0x62 U+FF42 b U+0062
0x63 U+FF43 c U+0063
0x64 U+FF44 d U+0064
0x65 U+FF45 e U+0065
0x66 U+FF46 f U+0066
0x67 U+FF47 g U+0067
0x68 U+FF48 h U+0068
0x69 U+FF49 i U+0069
0x6A U+FF4A j U+006A
0x6B U+FF4B k U+006B
0x6C U+FF4C l U+006C
0x6D U+FF4D m U+006D
0x6E U+FF4E n U+006E
0x6F U+FF4F o U+006F
0x70 U+FF50 p U+0070
0x71 U+FF51 q U+0071
0x72 U+FF52 r U+0072
0x73 U+FF53 s U+0073
0x74 U+FF54 t U+0074
0x75 U+FF55 u U+0075
0x76 U+FF56 v U+0076
0x77 U+FF57 w U+0077
0x78 U+FF58 x U+0078
0x79 U+FF59 y U+0079
0x7A U+FF5A z U+007A
0x7B U+FF5B { U+007B
0x7C U+FF5C | U+007C
0x7D U+FF5D } U+007D
0x7E U+FF5E ~ U+007E
  1. 其它特殊字符的全角和半角
半角字符 Unicode 全角字符 Unicode
U+2985 U+FF5F
U+2986 U+FF60
¢ U+00A2 U+FFE0
£ U+00A3 U+FFE1
¬ U+00AC U+FFE2
¯ U+00AF U+FFE3
¦ U+00A6 U+FFE4
¥ U+00A5 U+FFE5
U+20A9 U+FFE6
U+FFE8 U+2502
U+FFE9 U+2190
U+FFEA U+2191
U+FFEB U+2192
U+FFEC U+2193
U+FFED U+25A0
U+FFEE U+25CB

参考

[1]. https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2 [2]. http://www.voidcn.com/article/p-njiniuhl-nu.html [3]. https://www.jianshu.com/p/152e081fec1b

1
2
3
4
5
6
7
8
9
10
11
os.makedirs(path[, mode]) 
递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
输出在文件夹中的文件名通过在树中游走,向上或者向下。返回的是一个三元组(root,dirs,files),是一个生成器类型,需要用for遍历读取

os.chdir(path)
改变当前工作目录

os.listdir(path)
返回path指定的文件夹包含的文件或文件夹的名字的列表。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
import os
for root, dirs, files in os.walk(".", topdown=False):
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name))

path = "/var/www/html/"
dirs = os.listdir( path )
# 输出所有文件和文件夹
for file in dirs:
print (file)

os.walkos.listdir两个函数的区别在于前者会遍历到子文件夹中的子文件,而后者只是返回你传入的path中的文件夹名字和文件名字。

os库中有一个path的模块,专门用于处理文件path相关的属性信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
os.path.abspath(path)
返回绝对路径

os.path.basename(path)
返回文件名

os.path.exists(path)
如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。

os.path.join(path1[, path2[, ...]])
把目录和文件名合成一个路径

os.path.split(path)
把路径分割成 dirname 和 basename,返回一个元组

os.path.splitext(path)
分割路径,返回路径名和文件扩展名的元组

os.path.walk(path, visit, arg)
遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数

例子:

1
2
3
4
5
6
7
import os

print( os.path.basename('/root/runoob.txt') ) # 返回文件名
print( os.path.dirname('/root/runoob.txt') ) # 返回目录路径
print( os.path.split('/root/runoob.txt') ) # 分割文件名与路径
print( os.path.join('root','test','runoob.txt') ) # 将目录和文件名合成一个路径
print( os.path.splitext('/root/runoob.txt') )
1
2
3
4
5
runoob.txt
/root
('/root', 'runoob.txt')
root/test/runoob.txt
('/root/run/test', '.txt')

上面的split和splitext,前者分割出了文件名和路径,而后者可以分割出路径名和扩展名,如果想要获得文件的扩展名,可以用splitext,传入文件的path就可以了。

1
os.mknod(filename) 创建

复制文件和删除文件,移动文件

如果是删除一个目录,可以使用以下两种方式:

1
2
3
4
5
6
7
8
9
import shutil
# method 1
if os.path.exists(root_dir):
shutil.rmtree(root_dir) # 这里不可以使用os.removedirs(),removedirs只可以删除非空的文件夹,rmdir也是

# method 2
if len(os.listdir(root_dir)) > 0:
for file in os.scandir(root_dir):
os.remove(file.path)

如果想复制一个文件到另外一个文件夹,参考 https://zhuanlan.zhihu.com/p/35725217

1
copyfile(source_file, destination_file)

记住这里第二个参数一定要是可写入的文件名字,而不是目录。

移动文件

1
2
3
4
5
6
7
8
9
10
import shutil
import os

file_source = 'Path/Of/Directory'
file_destination = 'Path/Of/Directory'

get_files = os.listdir(file_source)

for g in get_files:
shutil.move(file_source + g, file_destination)

读写csv文件

第一个方式是用pandas,具体不介绍。

这里总结一下csv库

1
2
3
4
5
6
7
8
9
10
# 读取csv文件
with open(filename,'r') as csvfile:
csv_reader = csv.reader(csvfile)
for row in csv_reader:
print(row[1]) # 用列表的index取值
# 写csv文件
with open(filename,'w') as csvfile:
csv_writer = csv.writer(csvfile)
spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam']) # writerow接受一个list,所有值都会写在一行里
spamwriter.writerows([[],[],[]]) # writerows写入多行,每一行是一个列表,传进去的是列表的列表

除了写入list,还可以写字典类型的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# my data rows as dictionary objects 
mydict =[{'branch': 'COE', 'cgpa': '9.0', 'name': 'Nikhil', 'year': '2'},
{'branch': 'COE', 'cgpa': '9.1', 'name': 'Sanchit', 'year': '2'},
{'branch': 'IT', 'cgpa': '9.3', 'name': 'Aditya', 'year': '2'},
{'branch': 'SE', 'cgpa': '9.5', 'name': 'Sagar', 'year': '1'},
{'branch': 'MCE', 'cgpa': '7.8', 'name': 'Prateek', 'year': '3'},
{'branch': 'EP', 'cgpa': '9.1', 'name': 'Sahil', 'year': '2'}]

# field names
fields = ['name', 'branch', 'year', 'cgpa']

# name of csv file
filename = "university_records.csv"

# writing to csv file
with open(filename, 'w') as csvfile:
# creating a csv dict writer object
writer = csv.DictWriter(csvfile, fieldnames = fields)

# writing headers (field names)
writer.writeheader()

# writing data rows
writer.writerows(mydict)