1. 程式人生 > >IR中python 寫倒排索引與查詢處理

IR中python 寫倒排索引與查詢處理

學習資訊檢索課程,老師讓寫一個倒排索引與查詢處理的程式,於是抱著試試的心態自學python寫了出來。

整個沒有什麼太大的演算法技巧,唯一的就是查詢處理那裡遞迴函式正反兩次反覆查詢需要多除錯下。

資料結構:

#-*-coding:utf-8-*-
#!/usr/bin/python

'''
資料結構
建立索引
mydir   文件列表
onedoc  每一個文件
mydoc   當前查詢的文件

mywords 建立索引的字典
myindex 0 文件下標 1 單詞下標 2 次數 3...
wordcntdict中的個數 doccnt文件個數


三個字典
mywordsdictindex  單詞編號 起始位置
antimywordsdict   單詞編號 結束位置
mywordsdict       單詞->單詞編號

查詢
mypos是每個的單詞起始的index下標
myfindindex是每個單詞的標號,
mydocs 查詢到的文件號

'''
mydir=[]
mywords=[]
myindex=[]

mywordsdictindex={}
antimywordsdict={}
mywordsdict={}

wordcnt=0#dict中的個數
doccnt=0#文件個數
listcnt=0#index個數

mypos=[]
mydocs=[]
myfindindex=[]

mydoc=0
direct=0
print id(mydir)


建立索引:

#-*-coding:utf-8-*-
#!/usr/bin/python

from mydate import *
import sys
import os
import pprint
import pickle
def getmydoc(thepath,onedir):
	ans=[]
	for line in open(thepath+'/'+onedir):
		line=line.strip('\n')
		ans.append(line)
	return ans

def createindex(thepath):
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	mydir=os.listdir(thepath)
	for i in mydir:
		if(os.path.isdir(thepath+'/'+i)==True):
			mydir.remove(i)
	#print mydir
	mydir=['a.txt','b.txt','c.txt']
	wordcnt=0#dict中的個數
	doccnt=0#文件個數
	listcnt=0#index個數
	print id(wordcnt)
	for onedoc in mydir:
		mylist=getmydoc(thepath,onedoc)
		onedocword=0#每個詞在這個文字中的位置
		docworddict={}
		for myword in mylist:
			if(myword not in mywordsdict):
				mywords.append([0]*2)
				mywords[wordcnt][0]=myword
				mywordsdict[myword]=wordcnt
				wordcnt+=1
				#print myword,mywordsdict[myword]
			if(myword not in docworddict):
				docworddict[myword]=listcnt
				listcnt+=1
				myindex.append([0]*3)
			ins=docworddict[myword]
			myindex[ins][0]=doccnt
			myindex[ins][1]=mywordsdict[myword]
			myindex[ins][2]+=1
			myindex[ins].append(onedocword)
			onedocword+=1
		doccnt+=1
	myindex.sort(key=lambda x:x[1]) #sort
	beg=0
	fin=0
	for i in range(len(mywords)):
		mywordsdictindex[mywords[i][0]]=beg
		mywords[i][1]=beg	
		while fin <len(myindex) and myindex[fin][1]==i:#python不支援邏輯短路
			fin+=1
		beg=fin
	for i in range(len(mywords)):
		mywordsdictindex[i]=mywords[i][1]
		if(i==len(mywords)-1):
			antimywordsdict[i]=len(myindex)
		else:
			antimywordsdict[i]=mywords[i+1][1]
'''
	pprint.pprint (mywords)
	pprint.pprint (myindex)
	pprint.pprint (mywordsdict)
	pprint.pprint (mywordsdictindex)
	pprint.pprint (antimywordsdict)
	
	out=open("myindex.dat","wb")
	pickle.dump(myindex,out)
	out=open("mywords.dat","wb")
	pickle.dump(mywords,out)
'''

接收查詢與查詢處理:
#-*-coding:utf-8-*-
#!/usr/bin/python
#得到一個文字的列表
import sys
import os
import pprint
import pickle
import pdb
from mydate import *
'''
返回值三種:1 整個查詢詞都找到了 0 並沒有同時出現在一個文字中 -1 查詢完畢或不存在
mydoc 查詢詞是否都在這個文件中
direct 查詢方向 direct=0 遞歸向下,攜帶標記flag若為1則表明之前一直存在。0表明並不都在一個文字中那麼mydoc取過程中的最大值
      當到len(mypos)的時候,決定是否將該結果放入,並將最後一個詞的mypos後移 改變查詢方向,並返回1
      direct=1 遞迴返回,與0同樣操作,當到第0層再改變查詢方向
'''
def findword(loc,flag):
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	if(loc==len(mypos)):
		#pdb.set_trace()
		direct=1#############################
		if(flag==1):
			mydocs.append(mydoc)
			i=mypos[loc-1]+1
			#print mydocs
			if(i<antimywordsdict[myfindindex[loc-1]]):
				mydoc=myindex[i][0]
			else:
				return -1
		return 1
	i=mypos[loc]
	while i<antimywordsdict[myfindindex[loc]]:
		if(flag==-1):
			return -1
		if(loc==0 and direct==1):
			direct=0
		if( flag==1 and loc==0):
			mydocs.append(mydoc)#############################
			i+=1
			#print mydocs
			if(i<antimywordsdict[myfindindex[loc]]):
				mydoc=myindex[i][0]
			else:
				return 0		
		T=0
		while i<antimywordsdict[myfindindex[loc]] and myindex[i][0]<=mydoc:
			if(myindex[i][0]==mydoc):
				T=1
				break
			i+=1
		if(T==0):
			if(i+1==antimywordsdict[myfindindex[loc]]):
				return -1
			i+=1
			mydoc=myindex[i][0]
		mypos[loc]=i#############################
		if(flag==1 and T==1):
			pass
		else:
			T=0
		if(direct==1):
			return T
		flag=findword(loc+1,T)
	return 0




def getwords():
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	searchword=raw_input("find words\n")
	searchword=searchword.split(' ')
	flag=True
	for i in range(len(searchword)):
		if(searchword[i] not in mywordsdict):
			flag=False
			break
		myfindindex.append(mywordsdict[searchword[i]])#mypos是每個的單詞起始的index下標,myfindindex是每個單詞的標號,三個字典
		mypos.append(mywordsdictindex[searchword[i]])
		
	if(flag==False):
		print 'wrong'
		sys.exit()
	mydoc=myindex[mywordsdictindex[myfindindex[0]]][0]
	direct=0

	import pdb
	#pdb.set_trace()
	flag=findword(0,0)
	print mydocs#mydocs 查詢到的文件號 返回這個資料

使用:
#-*-coding:utf-8-*-
#!/usr/bin/python
import hwf
from mydate import *
import createindex
import sys
import os
import pprint
import pickle


createindex.createindex('.')#建立索引
hwf.getwords()#查詢單詞