2010-10-05 4 views
3
def makecounter(): 
    return collections.defaultdict(int) 

class RankedIndex(object): 
    def __init__(self): 
    self._inverted_index = collections.defaultdict(list) 
    self._documents = [] 
    self._inverted_index = collections.defaultdict(makecounter) 


def index_dir(self, base_path): 
    num_files_indexed = 0 
    allfiles = os.listdir(base_path) 
    self._documents = os.listdir(base_path) 
    num_files_indexed = len(allfiles) 
    docnumber = 0 
    self._inverted_index = collections.defaultdict(list) 

    docnumlist = [] 
    for file in allfiles: 
      self.documents = [base_path+file] #list of all text files 
      f = open(base_path+file, 'r') 
      lines = f.read() 

      tokens = self.tokenize(lines) 
      docnumber = docnumber + 1 
      for term in tokens: 
       if term not in sorted(self._inverted_index.keys()): 
        self._inverted_index[term] = [docnumber] 
        self._inverted_index[term][docnumber] +=1           
       else: 
        if docnumber not in self._inverted_index.get(term): 
         docnumlist = self._inverted_index.get(term) 
         docnumlist = docnumlist.append(docnumber) 
      f.close() 
    print '\n \n' 
    print 'Dictionary contents: \n' 
    for term in sorted(self._inverted_index): 
     print term, '->', self._inverted_index.get(term) 
    return num_files_indexed 
    return 0 

Je reçois une erreur d'index lors de l'exécution de ce code: liste d'index hors plage.Python: Dictionnaire de listes de listes

Le code ci-dessus génère un index de dictionnaire qui stocke le «terme» en tant que clé et les numéros de document dans lesquels le terme apparaît sous la forme d'une liste. Ex: si le terme 'chat' se produit dans les documents 1.txt, 5.txt et 7.txt le dictionnaire aura: chat < - [1,5,7]

Maintenant, je dois modifier pour ajouter une fréquence, si le mot chat apparaît deux fois dans le document 1, trois fois dans le document 5 et une fois dans le document 7: résultat attendu: terme < - [[numéro de document, terme fréquence], [numéro de document, terme fréquence]] < - Liste des listes dans un dict !!! cat < - [[1,2], [5,3], [7,1]]

J'ai joué avec le code, mais rien ne fonctionne. Je n'ai aucune idée de modifier cette infrastructure de données pour atteindre ce qui précède.

Merci d'avance.

Répondre

6

D'abord, utilisez une usine. Commencez par:

def makecounter(): 
    return collections.defaultdict(int) 

et utiliser plus tard

self._inverted_index = collections.defaultdict(makecounter) 

et comme la boucle for term in tokens:,

 for term in tokens: 
       self._inverted_index[term][docnumber] +=1 

Cela laisse dans chaque self._inverted_index[term] un dict tels que

{1:2,5:3,7:1} 

dans y notre exemple de cas. Puisque vous voulez la place dans chaque self._inverted_index[term] une liste de listes, puis juste après la fin du module de mise en boucle:

self._inverted_index = dict((t,[d,v[d] for d in sorted(v)]) 
          for t in self._inverted_index) 

Une fois fait (cette façon ou tout autre - je suis juste montrer une façon simple de construire !), cette structure de données sera alors aussi difficile à utiliser que vous l'avez rendue inutilement difficile à construire, bien sûr (la dict de dict est beaucoup plus utile et facile à utiliser et à construire), mais, viande d'homme & c ;-).

+0

J'ai fait les changements suggérés par vous. Je me rends compte que votre approche est beaucoup plus simple et claire que l'implémentation d'une liste de listes. Cependant, il me donne actuellement une erreur, j'ai modifié le code ci-dessus. – csguy11

+0

@csguy, dans votre méthode 'indexdir' (en supposant que ** est ** un, votre indentation comme indiqué ci-dessus est tout faux) vous détruisez complètement ce qui était précédemment assigné à' self.inversed_index' en lui assignant votre précédent, erroné structure de données, rendant ainsi vos modifications à votre code totalement et complètement non pertinentes.Vous ** réalisez ** que quand vous faites 'self.a = b' ça n'a plus d'importance dans tout le moins ** tout ce qui était déjà assigné à' self.a ', n'est-ce pas? –

+0

J'ai eu quel était le problème, mais comme je ne comprends pas vraiment votre implémentation, j'ai décidé de m'en tenir à ma méthode c'est-à-dire à la liste des listes, même si c'est trop compliqué. – csguy11

0

Peut-être que vous pourriez simplement créer une classe simple pour (nom doc, fréquence).

Votre dict pourrait alors avoir des listes de ce nouveau type de données. Vous pouvez également faire une liste de listes, mais un type de données distinct serait plus propre.

1

Voici un algorithme général que vous pouvez utiliser, mais vous devrez adapter votre code à celui-ci. Il génère une dict contenant un dictionnaire de comptes de mots pour chaque fichier.

filedicts = {} 
for file in allfiles: 
    filedicts[file] = {} 

    for term in terms: 
    filedict.setdefault(term, 0) 
    filedict[term] += 1 
Questions connexes