【问题标题】:Removing punctuation and creating a dictionary Python删除标点符号并创建字典 Python
【发布时间】:2018-03-24 01:49:06
【问题描述】:

我正在尝试创建一个函数来删除标点符号并将字符串中的每个字母小写。然后,它应该以字典的形式返回所有这些,计算字符串中的单词频率。

这是我目前写的代码:

def word_dic(string):
    string = string.lower()
    new_string = string.split(' ')
    result = {}

    for key in new_string:
        if key in result:
            result[key] += 1
        else:
            result[key] = 1

    for c in result:
        "".join([ c if not c.isalpha() else "" for c in result])

    return result

但这是我执行后得到的:

{'am': 3,
 'god!': 1,
 'god.': 1,
 'i': 2,
 'i?': 1,
 'thanks': 1,
 'to': 1,
 'who': 2}

我只需要删除单词末尾的标点符号。

【问题讨论】:

    标签: python python-3.x function dictionary punctuation


    【解决方案1】:

    另一种选择是使用著名的 Python 的batteries included

    >>> sentence = 'Is this a test? It could be!'
    >>> from collections import Counter
    >>> Counter(re.sub('\W', ' ', sentence.lower()).split())
    Counter({'a': 1, 'be': 1, 'this': 1, 'is': 1, 'it': 1, 'test': 1, 'could': 1})
    

    利用collections.Counter 计算单词,利用re.sub 替换所有非单词字符。

    【讨论】:

    • 不错(+1),但为了便于阅读,我会使用更多的行和变量。
    • 将非单词字符转换为空格,然后拆分,将使"it's" 被视为单词"it""s"。通常,您希望在空白处拆分,然后剥离标点符号,或者剥离标点符号并在空白处拆分,而不是将标点符号转换为空白。
    【解决方案2】:

    "".join([ c if not c.isalpha() else "" for c in result]) 创建一个没有标点符号的新字符串,但它没有任何事情;它会立即被丢弃,因为您从不存储结果。

    确实,做到这一点的最佳方法是规范化您的密钥将它们计入result。例如,您可能会这样做:

    for key in new_string:
        # Keep only the alphabetic parts of each key, and replace key for future use
        key = "".join([c for c in key if c.isalpha()])
        if key in result:
            result[key] += 1
        else:
            result[key] = 1
    

    现在result 从来没有带标点符号的键("god.""god!" 的计数仅在键 "god" 下相加),事后无需再通过一次来去除标点符号.

    或者,如果您只关心每个单词的前导和尾随标点符号(所以"it's" 应该保持原样,而不是转换为"its"),您可以进一步简化很多。只需import string,然后更改:

        key = "".join([c for c in key if c.isalpha()])
    

    到:

        key = key.rstrip(string.punctuation)
    

    这与您在问题中明确要求的内容相匹配(删除单词末尾的标点符号,但不删除开头或嵌入单词中的标点符号)。

    【讨论】:

    • 赞成包括选项。 Defaultdict int 会创建更紧凑的代码吗?
    • @AntonvBR:是的。并且collections.Counter 将更具解释性(具有等效行为)。也就是说,即使没有 defaultdict(int)(或任何类型的进口),您也可以使用 result[key] = result.get(key, 0) + 1 并避免使用 LBYL 四线以支持单线。
    • 嗨!我真的很感谢您的所有帮助 :) ShadowRanger 提供的代码确实提供了我想要的。我感到很恼火,因为我看到我快要拿到它了,我只是忘记将“”.join 部分存储在变量中。下次我会更加注意。非常感谢大家!!
    【解决方案3】:

    您可以使用string.punctuation 来识别标点符号,并在字符串被正确分解后使用collections.Counter 来计算出现次数。

    from collections import Counter
    from string import punctuation
    
    line = "It's a test and it's a good ol' one."
    
    Counter(word.strip(punctuation) for word in line.casefold().split())
    # Counter({"it's": 2, 'a': 2, 'test': 1, 'and': 1, 'good': 1, 'ol': 1, 'one': 1})
    

    使用str.strip 代替str.replace 可以保留诸如It's之类的词。

    str.casefold 方法只是str.lower 的一个更一般的情况。

    【讨论】:

      【解决方案4】:

      如果您以后想重复使用这些单词,您可以将它们与其出现次数一起存储在子词典中。每个单词都会在字典中占有一席之地。我们可以创建自己的函数来删除标点符号,非常简单。 看看下面的代码是否满足您的需求:

      def remove_punctuation(word):
          for c in word:
              if not c.isalpha():
                  word = word.replace(c, '')
          return word
      
      
      def word_dic(s):
          words = s.lower().split(' ')
          result = {}
      
          for word in words:
              word = remove_punctuation(word)
      
              if not result.get(word, None):
                  result[word] = {
                      'word': word,
                      'ocurrences': 1,
                  }
                  continue
              result[word]['ocurrences'] += 1  
      
          return result
      
      
      phrase = 'Who am I and who are you? Are we gods? Gods are we? We are what we are!'
      print(word_dic(phrase))
      

      你会得到这样的输出:

      { 'who': { 'word': 'who', 'ocurrences': 2}, 'am': { 'word': 'am', 'ocurrences': 1}, 'i': { 'word': 'i', 'ocurrences': 1}, 'and': { 'word': 'and', 'ocurrences': 1}, 'are': { 'word': 'are', 'ocurrences': 5}, 'you': { 'word': 'you', 'ocurrences': 1}, 'we': { 'word': 'we', 'ocurrences': 4}, 'gods': { 'word': 'gods', 'ocurrences': 2}, 'what': { 'word': 'what', 'ocurrences': 1} }

      然后您可以轻松访问每个单词及其出现,只需执行以下操作:

      word_dict(phrase)['are']['word']       # output: are
      word_dict(phrase)['are']['ocurrences'] # output: 5
      

      【讨论】:

      • 哇,这是一些主代码!非常感谢,这对我很有帮助,也教会了我很多!! :)
      • @Miguel2488,没问题。
      猜你喜欢
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 2015-07-07
      • 2018-05-13
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多