2015-08-19 3 views
1

Я пытаюсь создать цепочку марков в python. В настоящее время, когда у меня есть текст, такой как «Хотели бы вы» и «Хотелось бы», мой ключ кортежа («Будет», «вы») «может» перезаписывается, как стать («Будет»,) «нравится», когда я повторяю свой текстовый файл.Добавление к значению ключа в словаре

Я пытаюсь добавить каждое новое значение для ключа к значению для этого ключа. И.Е. для ключа ('будет', 'ты') Я хочу, чтобы значение, чтобы показать, как ("Would, 'вы'): 'может', 'как'

Вот мой код:

def make_chains(corpus): 
    """Takes an input text as a string and returns a dictionary of 
    markov chains.""" 
    dict = {} 
    for line in corpus: 
     line = line.replace(',', "") 
     words = line.split() 
     words_copy = words 
     for word in range(0, len(words_copy)): 
      #print words[word], words[word + 1] 
      if dict[(words[word], words[word + 1])] in dict: 
       dict.update(words[word+2]) 
      dict[(words[word], words[word + 1])] = words[word + 2] 
      #print dict 
      if word == len(words_copy) - 3: 
       break 

    return dict 
+0

посмотрите на 'collections.defaultdict'. – HuStmpHrrr

+0

Вы ищете 'defaultdict' в' collections'. Просто скажите 'd = collections.defaultdict (list)', и теперь каждый элемент представляет собой пустой список. Кстати, не назовите свою переменную 'dict', так как она столкнется с типом того же имени. – rlbond

ответ

2

простое решение

простое решение заключается в использовании collections.defaultdict:

from collections import defaultdict 


def make_chains(input_list): 
    """ 
    Takes an input text as a list of strings and returns a dictionary of markov chains. 
    """ 
    chain = defaultdict(list) 
    for line in input_list: 
     line = line.replace(',', "") 
     words = line.split() 
     for i in range(0, len(words) - 2): 
      chain[words[i], words[i + 1]].append(words[i + 2]) 

    return chain 

с этим, то вы получите:

$ print make_chains(["Would you like", "Would you could"]) 
defaultdict(<type 'list'>, {('Would', 'you'): ['like', 'could']}) 

Закрепление оригинального

Точно так же вы можете получить лучшее представление о том, что пошло не так в вашем коде, однако, мы можем зафиксировать оригинальное решение без использования defaultdict. Для этого есть несколько вещей, которые нужно упомянуть о вашем исходном коде.

Для начала, давайте посмотрим на это заявление:

words_copy = words 

Не делать то, что вы думаете, что делает, да и не нужно. Это не создает копию words, она просто создает новую переменную words_copy и указывает ее на существующее значение words. Поэтому, если вы меняете words, вы меняете words_copy.

Что бы вы хотели, это words_copy = copy.deepcopy(words), но это не нужно в этом случае, так как вы не меняете состояние words, когда выполняете итерацию.

Далее эта линия:

if dict[(words[word], words[word + 1])] in dict: 
    dict.update(words[word+2]) 

имеет несколько недостатков. Во-первых, если кортеж еще не указан в dict, то это вызовет ошибку ключа. Это наверняка произойдет на первой итерации. Во-вторых, метод обновления dict добавляет переданный dict к dict, который вы вызываете. То, что вы хотите сделать, это обновить значение dict на этом ключе.

Так что вы хотите:

if (words[word], words[word + 1]) in dict: 
    # Add to the existing list 
    dict(words[word], words[word + 1]).append(words[word+2]) 
else: 
    # Create a new list 
    dict(words[word], words[word + 1]) = [words[word+2]] 

Наконец, этот блок не является необходимым:

if word == len(words_copy) - 3: 
    break 

Вместо этого, просто итерацию до третьего по последнему индексу, как в:

for word in range(0, len(words) - 2): 

Введя это полностью, вы можете использовать эти изменения, чтобы исправить исходную версию:

def make_chains(corpus): 
    """Takes an input text as a string and returns a dictionary of 
    markov chains.""" 
    dict = {} 
    for line in corpus: 
     line = line.replace(',', "") 
     words = line.split() 
     for word in range(0, len(words) - 2): 
      if (words[word], words[word + 1]) in dict: 
       # Add to the existing list 
       dict[(words[word], words[word + 1])].append(words[word + 2]) 
      else: 
       # Create a new list 
       dict[(words[word], words[word + 1])] = [words[word + 2]] 

    return dict 

Надеюсь, это поможет!

+0

Спасибо, Рик! Это сработало. – MattGoldwater

+0

Замечательно, можете ли вы пометить этот ответ как принятый? –

+0

сделано. Расширенное объяснение было действительно полезно также! – MattGoldwater

Смежные вопросы