二维数据的特点就是数据锁定,就是对一个数据分量操作,另外一个也要同时得到相应的操作,就是说这两个数据具有联动性。
而对于我们非专业的,接触的几百万行数据,格式多为txt,而这种格式却无法保持联动性,而这也是我们处理此类问题需要解决的首要问题。
在这里我提供的解决思路就是利用Python中的字典进行操作。
字典的特点是:键唯一,但值随意。
这里的唯一就是一个很好的去重方式,但是考虑到二维数据的联动性,这里需要保证在去重的时候要删除对应的那个数据,这也就是上面说到的需要同步操作。
这里的解决思路就是利用另外一组数据作为索引,这个索引就是将两组数据联系起来的关键。
具体实例:有数据A,这里面的数据具有唯一性,数据B和数据C共同组成二维数据。其中A中数据和B种的数据同类型,而且A包含B,这里的要求就是把C中的数据填到A中。这里B,C数据不具有唯一性。
在处理这种大量数据的问题中效率显得非常重要,同时也要考虑硬件内存。
在这里我直接贴出我的代码
import re
import time
def fecth_Num(database_list):
start=time.perf_counter()
houzui=['zip\n','pdf\n','PDF','uvz\n','djvu\n','rar\n','RAR\n']#要保留的文件类型
names = locals()
ss_data = []#ss码
#打开文件
for inputfile_name in database_list:
names[inputfile_name] = open(inputfile_name+'.txt', "r",encoding='utf-8')
print('文件打开完毕,接下来进行合并排序')
for line in names[database_list[0]]:
spilt1=re.split(r'[._ ]',line)#点、横杆、空格
if spilt1[-1] in houzui:
if len(spilt1[-2])==8 and spilt1[-2].isdigit():
ss_data.append(spilt1[-2])
elif len(spilt1[0])==8 and spilt1[0].isdigit():
ss_data.append(spilt1[0])
else:
ss_data.append("s")
else:
ss_data.append("s")
print('匹配表去重完毕1,数据总条数:%d'%(len(ss_data)))
#booktitle_list=names[database_list[0]].readlines()#书名
path_list=names[database_list[1]].readlines()#路径名
names[database_list[0]].close()
names[database_list[1]].close()
key_list=list(range(0,len(ss_data)))#位置序号列表
print('匹配表去重完毕2,路径条数:%d'%(len(path_list)))
booktitle_dict=dict(zip(ss_data,key_list))
path_dict_1=dict(zip(key_list,path_list))
fin_path_list=[]
print('匹配表去重完毕3,文件名去重后数量:%d'%(len(booktitle_dict)))
#key_list_bu=set(key_list)-set(booktitle_dict.values())#计算键的补集
for key in list(booktitle_dict.values()):
fin_path_list.append(path_dict_1[key])
print('匹配表去重完毕4,路径名去重后数量:%d'%(len(path_dict_1)))
ss_path_dict=dict(zip(booktitle_dict.keys(),fin_path_list))
end=time.perf_counter()
print('共耗时:'+str(end-start))
print("fectch_num运行完毕")
return ss_path_dict
def ss_path(ss_path,fin_ss):#参数分别是汇总地址 和汇总ss码文件
start=time.perf_counter()
ss_list=open(fin_ss+'.txt',"r",encoding='utf-8')
fin_list=ss_list.read().splitlines()#需要的纯ss码的txt文件.splitlines(),合并版的键
ss_list.close()
fin_value_list=[' ']*len(fin_list)#合并版的值
fin_dict=dict(zip(fin_list,fin_value_list))
fin_dictMerged1 = fin_dict.copy()#合并字典
fin_dictMerged1.update(ss_path)#合并字典
end=time.perf_counter()
print("ss_path运行完毕,运行时间:%f"%(end-start))
return list(fin_dictMerged1.values())
def ss_path_write(qianzui_ss,ss_path):
start=time.perf_counter()
out_qianzui_ss_name="out_qianzui_ss.txt"
out_qianzui_ss=open(out_qianzui_ss_name, "w",encoding='utf-8')#目标文件
qianzui_ss_list=open(qianzui_ss+'.txt',"r",encoding='utf-8')
i=0
jiangefu=' '
for line in qianzui_ss_list:
out_qianzui_ss.write(line)
out_qianzui_ss.write(str(ss_path[i]))
i+=1
qianzui_ss_list.close()
out_qianzui_ss.close()
end=time.perf_counter()
print("ss_path_write运行完毕,运行时间:%f"%(end-start))
def takeSecond(elem):#排序函数
return elem[0]
ss_dict=fecth_Num(['文件名','路径'])
ss_path1=ss_path(ss_dict,'合并版')
ss_path_write('前缀_合并版',ss_path1)
代码共计:三个函数由上到下依次解决依据数据B先对数据B和数据C组成的二维数据进行去重,得到了以b为键,c为值的字典,之后将A的值作为键组成一个字典,并将上个函数返回的字典更新到其中,最后一个函数是将目标数据写入txt文件的
文件打开完毕,接下来进行合并排序
匹配表去重完毕1,数据总条数:3061192
匹配表去重完毕2,路径条数:3061192
匹配表去重完毕3,文件名去重后数量:2788886
匹配表去重完毕4,路径名去重后数量:3061192
共耗时:9.680296399999861
fectch_num运行完毕
ss_path运行完毕,运行时间:2.337771
3335653
ss_path_write运行完毕,运行时间:4.885455
上述运行结果:300w行左右的数据总运行时间17s左右,这已经满足我需求了。