2013-03-10 3 views
0

В настоящее время я пытаюсь создать индекс слов, прочитывая каждую строку из текстового файла и проверяя, находится ли это слово в этой строке. Если это так, он печатает цифровую строку и продолжает проверку. Я работал над тем, как я хотел, когда печатал каждое слово и номер строки, но я не уверен, какую систему хранения я мог бы использовать, чтобы содержать каждый номер.Создание индекса слов

Пример кода:

def index(filename, wordList): 
    'string, list(string) ==> string & int, returns an index of words with the line number\ 
    each word occurs in' 
    indexDict = {} 
    res = [] 
    infile = open(filename, 'r') 
    count = 0 
    line = infile.readline() 
    while line != '': 
     count += 1 
     for word in wordList: 
      if word in line: 
       #indexDict[word] = [count] 
       print(word, count) 
     line = infile.readline() 
    #return indexDict 

Это печатает слово и независимо от количества которое в то время (номер строки), но то, что я пытаюсь сделать, это сохранить номера, так что позже я могу сделать распечатать

word linenumber 

word2 linenumber, linenumber 

И так далее. Я чувствовал, словарь будет работать для этого, если я ставлю каждый номер строки внутри списка, так что каждый ключ может содержать более одного значения, но ближайший я получил это:

{'mortal': [30], 'dying': [9], 'ghastly': [82], 'ghost': [9], 'raven': [120], 'evil': [106], 'demon': [122]} 

Когда я хотел, чтобы показать, как :

{'mortal': [30], 'dying': [9], 'ghastly': [82], 'ghost': [9], 'raven': [44, 53, 55, 64, 78, 97, 104, 111, 118, 120], 'evil': [99, 106], 'demon': [122]} 

Любые идеи?

+1

Возможно, вам нужен defaultdict по умолчанию для [new] и добавление. Разумеется, ваша прокомментированная строка просто перезаписывает ключ с 1-позиционным списком каждый раз. – geoffspear

+0

Для всех, кто ответил, благодарю вас за ввод. Это было очень оценено. – iKyriaki

ответ

2

Вы заменяете старое значение этой линии

indexDict[word] = [count] 

Изменение его

indexDict[word] = indexDict.setdefault(word, []) + [count] 

даст ответ, который вы хотите. Он получит текущее значение indexDict [word] и добавит к нему новый счет, если нет indexDict [word], он создает новый пустой список и добавляет к нему счет.

+0

Это на самом деле то, что мне нужно. Большое спасибо. – iKyriaki

+2

@iKyriaki: Решения 'defaultdict' делают то же самое, в более компактном синтаксисе. –

+0

NP. Вы выбираете словарь, поэтому я использую словарь, чтобы помочь вам. Я не понимаю, почему некоторые люди переписывают ваш код с помощью коллекций. – octref

3

попробовать что-то вроде этого:

import collections 
def index(filename, wordList): 
    indexDict = collections.defaultdict(list) 
    with open(filename) as infile: 
     for (i, line) in enumerate(infile.readlines()): 
      for word in wordList: 
       if word in line: 
        indexDict[word].append(i+1) 
    return indexDict 

Это дает те же результаты, как в вашем примере (с помощью Raven Эдгара По).

В качестве альтернативы вы можете использовать обычный dict вместо defaultdict и инициализировать его всеми словами в списке; чтобы убедиться, что indexDict содержит запись даже для слов, которые не указаны в тексте.

Также обратите внимание на использование enumerate. Эта встроенная функция очень полезна для итерации как индекса, так и элемента в этом индексе некоторого списка (например, строки в файле).

+1

Для номеров строк имеет смысл начать с 1 вместо нуля. Вы можете сделать это с помощью 'enumerate (infile, 1)', а затем один '.append (i)' –

2

Существует, вероятно, более вещий способ, чтобы написать это, но только для удобства чтения, вы можете попробовать это (простой пример):

dict = {1: [], 2: [], 3: []} 

list = [1,2,2,2,3,3] 

for k in dict.keys(): 
    for i in list: 
     if i == k: 
      dict[k].append(i) 


In [7]: dict 
Out[7]: {1: [1], 2: [2, 2, 2], 3: [3, 3]} 
+0

Это добавит _lines_, а не номера строк! –

+0

Я использовал цифры, чтобы показать логику, подумал, что уже добавлено значение индекса строки, «count + = 1». Лазз опустится. –

1

Вы должны добавить свой следующий элемент в списке, если список уже существует.

Самый простой способ получить список уже быть там, даже в первый раз, когда вы найдете слово, чтобы использовать collections.defaultdict class отслеживать слово к-линии отображения:

from collections import defaultdict 

def index(filename, wordList): 
    indexDict = defaultdict(list) 
    with open(filename, 'r') as infile: 
     for i, line in enumerate(infile): 
      for word in wordList: 
       if word in line: 
        indexDict[word].append(i) 
        print(word, i) 

    return indexDict 

Я упрощенный ваш код немного использует лучшие практики; открывая файл в качестве менеджера контекста, чтобы он автоматически закрывался по завершении и с помощью enumerate() для создания номеров строк на лету.

Возможно, вы немного ускорите это движение (и сделайте его более точным), если бы вы превратили свои строки в набор слов (возможно, но это не приведет к удалению пунктуации), так как тогда вы можете использовать множество пересечений тесты против wordList (также набор), которые могут быть значительно быстрее, чтобы найти соответствующие слова.

+0

Что случилось с вашей переменной 'count'? должен htis: 'indexDict [word] .append (count) 'be this' indexDict [word] .append (i)'? И что такое 'res'? – hughdbrown

+0

Кроме того, если вы собираетесь быть единственным человеком, который упоминает 'defaultdict', вы можете также упомянуть' collections.Counter', хотя я недостаточно понимаю пример использования OP, чтобы определить, является ли подсчет экземпляров идеей. – hughdbrown

+0

Плохое редактирование; спасибо, что указали эти ошибки. Я считал, что упоминаю «Счетчик», но отклонил его; это API слишком много для этой утилиты. –