У меня есть файл, который содержит большое количество текста. Я читаю этот файл и намереваюсь распечатать количество ссылок на отрывок из Библии, отмеченных строкой, начинающейся с «Стих». Затем я хочу распечатать ссылку с указанием количества вхождений.

Пример файла:

Verse- Matthew 5:2
Commentary- Matthew
Verse- Matthew 10:5
Verse- John 3:16
Commentary- John
Verse- Luke 5:2
Commentary- Luke

Результаты должны быть примерно такими:

{'5:2': 2, '10:5': 1, '3:16': 1}

Я использую словарь, чтобы сделать ключ: значение ссылки: вхождения. Сценарий короткий и предоставляется:

fileHandle = open("sj", "r")
occurrences = dict()
references = []
#Go through each line if it is a verse line (starts with "Verse"), seperate the reference and count the reference
for line in fileHandle:
    if "Verse" in line:
        verseLine = line.split()
        references.append(verseLine[2]) #Reference is always 3rd index
        for reference in references:
            if reference not in occurrences:
                occurrences[reference] = 1
            else:
                occurrences[reference] = occurrences[reference] + 1
print(" References printed below ")
print(references)
print(" Occerances printed below ")
print(occurrences)

Проблема: ссылки подсчитываются странным образом. Это мой вывод:

{'5:2': 5, '10:5': 3, '3:16': 2}

Очевидно, что это не так! Это как-то связано с утверждением else:, я думаю. Например, если я изменю его на occurrences[reference] = occurrences[reference] + 2 (обратите внимание, что 1 изменился на 2), я ожидаю, что результаты удвоятся. Но они не

{'5:2': 9, '10:5': 5, '3:16': 3}

Почему этот подсчет не считается правильно?

0
Reubens4Dinner 26 Июн 2019 в 18:31

4 ответа

Лучший ответ

Список references обрабатывается для каждой строки со строкой "Verse", поэтому сценарий перезагружается.

Переместите цикл references из цикла line.

fileHandle = open("sj", "r")
occurrences = dict()
references = []
#Go through each line if it is a verse line (starts with "Verse"), seperate the reference and count the reference
for line in fileHandle:
    if "Verse" in line:
        verseLine = line.split()
        references.append(verseLine[2]) #Reference is always 3rd index

# After indexing every verse you can start counting them
for reference in references:
    if reference not in occurrences:
        occurrences[reference] = 1
    else:
        occurrences[reference] = occurrences[reference] + 1

print(" References printed below ")
print(references)
print(" Occerances printed below ")
print(occurrences)

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

fileHandle = open("sj", "r")
occurrences = dict()

#Go through each line if it is a verse line (starts with "Verse"), seperate the reference and count the reference
for line in fileHandle:
    if "Verse" in line:
        verseLine = line.split()
        try:
            occurrences[verseLine[2]] += 1
        except KeyError:
            occurrences[verseLine[2]] = 1

fileHandle.close()
print(" References printed below ")
print(references)
print(" Occerances printed below ")
print(occurrences)
2
Layo 26 Июн 2019 в 16:00

Вот несколько предложений по улучшению вашего кода:

  • используйте with open('test.txt') as f, чтобы не забыть закрыть файл в конце
  • используйте collections.Counter для работы по подсчету
  • Вы хотите использовать только номера глав и стихов, или вы должны также включить название книги?

Мой код:

import collections
c = collections.Counter()

with open('test.txt') as f:
    for line in f:
        line = line.strip()
        if len(line) > 0:
            if line.startswith('Verse'):
                data = line[6:]               # Book, chapter and verse number
                # data = line.split()[2]      # only chapter and verse number

                c.update({data: 1})

print('all:')
for k, count in c.items():
    print(' ', count, k)

print('most common:')
for k, count in c.most_common(1):
    print(' ', count, k)
2
Ralf 26 Июн 2019 в 15:49

Другая версия, использующая re и collections.Counter:

data = '''Verse- Matthew 5:2
Commentary- Matthew
Verse- Matthew 10:5
Verse- John 3:16
Commentary- John
Verse- Luke 5:2
Commentary- Luke'''

import re
from collections import Counter

c = Counter( re.findall(r'^Verse.*?(\d+:\d+)$', data, flags=re.M) )
print(dict(c))

Печать :

{'5:2': 2, '10:5': 1, '3:16': 1}
2
Andrej Kesely 26 Июн 2019 в 15:52

Вот фиксированный код

fileHandle = open("sj", "r")
occurrences = dict()
references = []
# Go through each line if it is a verse line (starts with "Verse"), seperate the reference and count the reference
for line in fileHandle:
    if line.startswith("Verse"):
        verseLine = line.split()
        try:
            occurrences[verseLine[2]] += 1  # Reference is always 3rd index
        except KeyError:
            occurrences[verseLine[2]] = 1
print(" References printed below ")
print(references)
print(" Occerances printed below ")
print(occurrences)

Я думаю, что это происходит потому, что вы увеличиваете значение вхождения всех ссылок для каждой строки, содержащей 'Verse'. (обратите внимание, что я изменил "Verse" in line на line.startswith("Verse"), so the code will only execute if the line starts with «Стих» `.

1
בנימין כהן 26 Июн 2019 в 15:43