首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何总结对话中每个人的字数?

如何总结对话中每个人的字数?
EN

Stack Overflow用户
提问于 2011-09-15 11:13:07
回答 3查看 2.2K关注 0票数 2

我开始学习Python,我正在尝试编写一个程序来导入一个文本文件,计算单词的总数,计算特定段落中的单词数(由每个参与者说,由'P1','P2‘等描述),排除这些单词(即'P1‘等)从我的字数,并分别打印段落。

多亏了@James Hurford,我得到了以下代码:

代码语言:javascript
复制
words = None
with open('data.txt') as f:
   words = f.read().split()
total_words = len(words)
print 'Total words:', total_words

in_para = False
para_type = None
paragraph = list()
for word in words:
  if ('P1' in word or
      'P2' in word or
      'P3' in word ):
      if in_para == False:
         in_para = True
         para_type = word
      else:
         print 'Words in paragraph', para_type, ':', len(paragraph)
         print ' '.join(paragraph)
         del paragraph[:]
         para_type = word
  else:
    paragraph.append(word)
else:
  if in_para == True:
    print 'Words in last paragraph', para_type, ':', len(paragraph)
    print ' '.join(paragraph)
  else:
    print 'No words'

我的文本文件如下:

P1: Bla bla bla.

P2:.

P1:。

P3: Bla.

我需要做的下一部分是总结每个参与者的单词。我只能打印它们,但是我不知道如何返回/重用它们。

我将需要一个新的变量,每个参与者的字数,我以后可以操作,除了总结每个参与者说的所有的话,例如。

代码语言:javascript
复制
P1all = sum of words in paragraph

有没有办法把“you‘s”或"it's“等数成两个单词?

有什么办法解决吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-04 03:06:50

恭喜你用Python开始你的冒险!并不是这篇文章中的每一件事现在都有意义,但是如果它以后有帮助的话,就把它书签上书签,然后再回来。最后,您应该尝试从脚本到软件工程,以下是一些您的想法!

强大的力量带来了巨大的责任,作为Python开发人员,您需要比其他不掌握您的手并执行“好”设计的语言更加自律。

我发现从自上而下的设计开始很有帮助。

代码语言:javascript
复制
def main():
    text = get_text()
    p_text = process_text(text)
    catalogue = process_catalogue(p_text)

轰隆隆!你刚刚写了整个程序--现在你只需要回到并填空!当你这样做的时候,看起来就没那么吓人了。就我个人而言,我认为自己不够聪明,不能解决很大的问题,但我是解决小问题的专家。所以让我们一次处理一件事。我将从'process_text‘开始。

代码语言:javascript
复制
def process_text(text):
    b_text = bundle_dialogue_items(text)   
    f_text = filter_dialogue_items(b_text)
    c_text = clean_dialogue_items(f_text)

我还不太清楚这些东西意味着什么,但我知道文本问题倾向于遵循一种叫做“map/ then”的模式,这意味着您对一些东西执行和操作,然后清理它并组合起来,所以我添加了一些占位符函数。如果需要的话,我可能会回去再加更多。

现在让我们来写“过程目录”。我本可以写"process_dict“,但对我来说这听起来很蹩脚。

代码语言:javascript
复制
def process_catalogue(p_text): 
    speakers = make_catalogue(c_text)
    s_speakers = sum_words_per_paragraph_items(speakers)
    t_speakers = total_word_count(s_speakers)

凉爽的。不算太坏。你可能和我不同,但我认为把项目汇总起来,按段落数单词,然后计算所有的单词是有意义的。

因此,在这一点上,我可能会创建一个或两个小的'lib‘(库)模块来备份剩余的函数。为了让您能够在不担心导入的情况下运行这些文件,我将把它们都放在一个.py文件中,但最终您将学习如何将它们分解,使其看起来更好看。那我们就这么做吧。

代码语言:javascript
复制
# ------------------ #
# == process_text == #
# ------------------ #

def bundle_dialogue_items(lines):
    cur_speaker = None
    paragraphs = Counter()
    for line in lines:
        if re.match(p, line):
            cur_speaker, dialogue = line.split(':')
            paragraphs[cur_speaker] += 1
        else:
            dialogue = line

        res = cur_speaker, dialogue, paragraphs[cur_speaker]
        yield res


def filter_dialogue_items(lines):
    for name, dialogue, paragraph in lines:
        if dialogue:
            res = name, dialogue, paragraph
            yield res

def clean_dialogue_items(flines):
    for name, dialogue, paragraph in flines:
        s_dialogue = dialogue.strip().split()
        c_dialouge = [clean_word(w) for w in s_dialogue]
        res = name, c_dialouge, paragraph
        yield res

a和一个小助手函数

代码语言:javascript
复制
# ------------------- #
# == aux functions == #
# ------------------- #

to_clean = string.whitespace + string.punctuation
def clean_word(word):
    res = ''.join(c for c in word if c not in to_clean)
    return res

因此,这可能并不明显,但这个库是作为一个数据处理管道设计的。有几种处理数据的方法,一种是流水线处理,另一种是批量处理。让我们看一看批处理。

代码语言:javascript
复制
# ----------------------- #
# == process_catalogue == #
# ----------------------- #

speaker_stats = 'stats'
def make_catalogue(names_with_dialogue):
    speakers = {}
    for name, dialogue, paragraph in names_with_dialogue:
        speaker = speakers.setdefault(name, {})
        stats = speaker.setdefault(speaker_stats, {})
        stats.setdefault(paragraph, []).extend(dialogue)
    return speakers



word_count = 'word_count'
def sum_words_per_paragraph_items(speakers):
    for speaker in speakers:
        word_stats = speakers[speaker][speaker_stats]
        speakers[speaker][word_count] = Counter()
        for paragraph in word_stats:
            speakers[speaker][word_count][paragraph] += len(word_stats[paragraph])
    return speakers


total = 'total'
def total_word_count(speakers):
    for speaker in speakers:
        wc = speakers[speaker][word_count]
        speakers[speaker][total] = 0
        for c in wc:
            speakers[speaker][total] += wc[c]
    return speakers

所有这些嵌套字典都变得有点复杂。在实际的生产代码中,我会用一些更易读的类来替换这些类(同时添加测试和文档字符串!),但是我不想让它变得更加混乱!好吧,为了你的方便,下面是整件事的集合。

代码语言:javascript
复制
import pprint
import re
import string
from collections import Counter

p = re.compile(r'(\w+?):')


def get_text_line_items(text):
    for line in text.split('\n'):
        yield line


def bundle_dialogue_items(lines):
    cur_speaker = None
    paragraphs = Counter()
    for line in lines:
        if re.match(p, line):
            cur_speaker, dialogue = line.split(':')
            paragraphs[cur_speaker] += 1
        else:
            dialogue = line

        res = cur_speaker, dialogue, paragraphs[cur_speaker]
        yield res


def filter_dialogue_items(lines):
    for name, dialogue, paragraph in lines:
        if dialogue:
            res = name, dialogue, paragraph
            yield res


to_clean = string.whitespace + string.punctuation


def clean_word(word):
    res = ''.join(c for c in word if c not in to_clean)
    return res


def clean_dialogue_items(flines):
    for name, dialogue, paragraph in flines:
        s_dialogue = dialogue.strip().split()
        c_dialouge = [clean_word(w) for w in s_dialogue]
        res = name, c_dialouge, paragraph
        yield res


speaker_stats = 'stats'


def make_catalogue(names_with_dialogue):
    speakers = {}
    for name, dialogue, paragraph in names_with_dialogue:
        speaker = speakers.setdefault(name, {})
        stats = speaker.setdefault(speaker_stats, {})
        stats.setdefault(paragraph, []).extend(dialogue)
    return speakers


def clean_dict(speakers):
    for speaker in speakers:
        stats = speakers[speaker][speaker_stats]
        for paragraph in stats:
            stats[paragraph] = [''.join(c for c in word if c not in to_clean)
                                for word in stats[paragraph]]
    return speakers


word_count = 'word_count'


def sum_words_per_paragraph_items(speakers):
    for speaker in speakers:
        word_stats = speakers[speaker][speaker_stats]
        speakers[speaker][word_count] = Counter()
        for paragraph in word_stats:
            speakers[speaker][word_count][paragraph] += len(word_stats[paragraph])
    return speakers


total = 'total'


def total_word_count(speakers):
    for speaker in speakers:
        wc = speakers[speaker][word_count]
        speakers[speaker][total] = 0
        for c in wc:
            speakers[speaker][total] += wc[c]
    return speakers


def get_text():
    text = '''BOB: blah blah blah blah
blah hello goodbye etc.

JERRY:.............................................
...............

BOB:blah blah blah
blah blah blah
blah.
BOB: boopy doopy doop
P1: Bla bla bla.
P2: Bla bla bla bla.
P1: Bla bla.
P3: Bla.'''
    text = get_text_line_items(text)
    return text


def process_catalogue(c_text):
    speakers = make_catalogue(c_text)
    s_speakers = sum_words_per_paragraph_items(speakers)
    t_speakers = total_word_count(s_speakers)
    return t_speakers


def process_text(text):
    b_text = bundle_dialogue_items(text)
    f_text = filter_dialogue_items(b_text)
    c_text = clean_dialogue_items(f_text)
    return c_text


def main():

    text = get_text()
    c_text = process_text(text)
    t_speakers = process_catalogue(c_text)

    # take a look at your hard work!
    pprint.pprint(t_speakers)


if __name__ == '__main__':
    main()

因此,对于这个应用程序来说,这个脚本几乎肯定是多余的,但重点是要看到可读的、可维护的、模块化的Python代码可能是什么样子(值得怀疑)。

非常确定的输出如下所示:

代码语言:javascript
复制
{'BOB': {'stats': {1: ['blah',
                       'blah',
                       'blah',
                       'blah',
                       'blah',
                       'hello',
                       'goodbye',
                       'etc'],
                   2: ['blah',
                       'blah',
                       'blah',
                       'blah',
                       'blah',
                       'blah',
                       'blah'],
                   3: ['boopy', 'doopy', 'doop']},
         'total': 18,
         'word_count': Counter({1: 8, 2: 7, 3: 3})},
 'JERRY': {'stats': {1: ['', '']}, 'total': 2, 'word_count': Counter({1: 2})},
 'P1': {'stats': {1: ['Bla', 'bla', 'bla'], 2: ['Bla', 'bla']},
        'total': 5,
        'word_count': Counter({1: 3, 2: 2})},
 'P2': {'stats': {1: ['Bla', 'bla', 'bla', 'bla']},
        'total': 4,
        'word_count': Counter({1: 4})},
 'P3': {'stats': {1: ['Bla']}, 'total': 1, 'word_count': Counter({1: 1})}}
票数 1
EN

Stack Overflow用户

发布于 2011-09-15 11:26:06

我需要一个新变量,为我以后可以操作的每个参与者设置单词计数。

不,您需要一个Counter (Python 2.7+,否则使用defaultdict(int))将人映射到单词计数。

代码语言:javascript
复制
from collections import Counter
#from collections import defaultdict

words_per_person = Counter()
#words_per_person = defaultdict(int)

for ln in inputfile:
    person, text = ln.split(':', 1)
    words_per_person[person] += len(text.split())

现在,words_per_person['P1']包含了P1的字数,假设text.split()对于您来说是一个足够好的标记器。(语言学家对单词的定义存在分歧,所以你总是会得到一个近似词。)

票数 5
EN

Stack Overflow用户

发布于 2011-09-15 22:37:42

你可以用两个变量来做这件事。一种是为了记录谁在说话,另一种是为说话的人保留段落。为了存储段落,并将该段落属于谁,则该段落属于使用与该人作为键的dict和与该键相关的该人所说的段落的列表。

代码语言:javascript
复制
para_dict = dict()
para_type = None

for word in words:
    if ('P1' in word or
        'P2' in word or
        'P3' in word ):
        #extract the part we want leaving off the ':'
        para_type = word[:2]
        #create a dict with a list of lists 
        #to contain each paragraph the person uses
        if para_type not in para_dict:
            para_dict[para_type] = list()
        para_dict[para_type].append(list())
    else:
        #Append the word to the last list in the list of lists
        para_dict[para_type][-1].append(word)

从这里你可以总结出这样说出的字数。

代码语言:javascript
复制
for person, para_list in para_dict.items():
    counts_list = list()
    for para in para_list:
        counts_list.append(len(para))
    print person, 'spoke', sum(counts_list), 'words'
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7429845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档