Причина в том, что вы должны аннулировать ham_count
, а не только обновлять spam_count
и наоборот.
Перепишите
if is_spam == '1':
current_word, spam_count = word, count
else:
current_word, ham_count = word, count
как
if is_spam == '1':
current_word, spam_count = word, count
ham_count = 0
else:
current_word, ham_count = word, count
spam_count = 0
Тем не менее, выходной сигнал не будет точно таким же, как в вашем выводе
1), потому что вы всегда сначала печатаете spam_count
(но в примере вывода «cat ham» выдает раньше)
2) выводБлок генерирует только спам или только хам, в зависимости от текущего состояния переменной is_spam
, но я предполагаю, что вы планируете все это выдавать, верно?
The output:
dog 1 2
dog 0 2
cat 1 1
- есть правильный счет "cat"спам », но не« кошачья ветчина »- и я полагаю, вам следует хотя бы напечатать что-то вроде этого:
переписать этот код
if current_word == word:
if is_spam == '1':
print(f'{current_word}\t{is_spam}\t{spam_count}')
else:
print(f'{current_word}\t{is_spam}\t{spam_count}')
как
print(f'{current_word}\t{1}\t{spam_count}')
print(f'{current_word}\t{0}\t{ham_count}')
- и полным выводом будет
dog 1 2
dog 0 2
cat 1 1
cat 0 2
Itertools
Кроме того, модуль itertools отлично подходит для подобных задач:
import itertools
splitted_lines = map(lambda x: x.split('\t'), data.splitlines())
grouped = itertools.groupby(splitted_lines, lambda x: x[0])
grouped
является объектом itertools.goupby и его генератором - поэтому будьте осторожны, он ленив и возвращает значения только один раз (поэтому я показываю вывод еепросто как пример, потому что он использует значения генератора)
[(gr_name, list(gr)) for gr_name, gr in grouped]
Out:
[('dog',
[['dog', '1', '1'],
['dog', '1', '1'],
['dog', '0', '1'],
['dog', '0', '1']]),
('cat', [['cat', '0', '1'], ['cat', '0', '1'], ['cat', '1', '1']])]
Хорошо, теперь каждая группа может быть снова сгруппирована по ее is_spam
geature:
import itertools
def sum_group(group):
"""
>>> sum_group([('1', [['dog', '1', '1'], ['dog', '1', '1']]), ('0', [['dog', '0', '1'], ['dog', '0', '1']])])
[('1', 2), ('0', 2)]
"""
return sum([int(i[-1]) for i in group])
splitted_lines = map(lambda x: x.split('\t'), data.splitlines())
grouped = itertools.groupby(splitted_lines, lambda x: x[0])
[(name, [(tag_name, sum_group(sub_group))
for tag_name, sub_group
in itertools.groupby(group, lambda x: x[1])])
for name, group in grouped]
Out:
[('dog', [('1', 2), ('0', 2)]), ('cat', [('0', 2), ('1', 1)])]
Завершите пример через itertools:
import itertools
def emit_group(name, tag_name, group):
tag_sum = sum([int(i[-1]) for i in group])
print(f"{name}\t{tag_name}\t{tag_sum}") # emit here
return (name, tag_name, tag_sum) # return the same data
splitted_lines = map(lambda x: x.split('\t'), data.splitlines())
grouped = itertools.groupby(splitted_lines, lambda x: x[0])
emitted = [[emit_group(name, tag_name, sub_group)
for tag_name, sub_group
in itertools.groupby(group, lambda x: x[1])]
for name, group in grouped]
Out:
dog 1 2
dog 0 2
cat 0 2
cat 1 1
- emitted
содержит список кортежей с одинаковыми данными.Поскольку это ленивый подход, он отлично работает с потоками; здесь - хороший учебник по iterools, если вам интересно.