【问题标题】:Programming concept编程概念
【发布时间】:2013-02-18 14:15:39
【问题描述】:

我想制作一个程序,使用积分系统从垃圾邮件中分类邮件。

对于邮件中的几句话,
我希望程序为我在程序中归类为“垃圾词”的每个单词给出不同的分数,我还为不同的单词分配不同的分数,以便每个单词都值得一些分数。

我的伪代码:

  1. 从文件中读取文本
  2. 寻找“垃圾词”
    • 对于出现的每个单词,给出该单词的价值。
  3. 如果每个垃圾词的总分为 10,则打印“SPAM”,后跟文件中分类为垃圾词及其得分的单词列表。

示例(文本文件):

Hello!  
Do you have trouble sleeping? 
Do you need to rest?
Then dont hesitate call us for the absolute solution- without charge!

因此,当程序运行并分析上面的文本时,它应该如下所示:

SPAM 14p
trouble 6p
charge 3p 
solution 5p 

所以我打算这样写:

class junk(object):
    fil = open("filnamne.txt","r")
    junkwords = {"trouble":"6p","solution":"3p","virus":"4p"}
    words = junkwords

    if words in fil:
        print("SPAM")
    else:
        print("The file doesn't contain any junk")

所以我现在的问题是如何为文件中出现的列表中的每个单词打分?
以及如何对总分求和以便if total_points are > 10 那么程序应该print "SPAM",
接下来是文件中找到的“垃圾词”列表以及每个词的总分。..

【问题讨论】:

  • 为什么会在每个单词后打印“14 p”、“6 p”等?每个单词的分数是否不同?如果是这样,这与您之前的要求“出现的每个单词给出 1 分”的要求相冲突
  • @Kevin 是的,每个单词都值不同的分数,忘记思考“出现的每个单词都给 1 分”
  • 这些积分保存在哪里?垃圾词应该是字典。
  • 是的,当然应该,应该需要改变我的计划才知道。但真正的问题仍然存在......
  • 如果一个词出现不止一次,该点值会被多次添加吗?

标签: data-structures python-3.x string-matching


【解决方案1】:

这是一个快速脚本,可能会让您接近那里:

MAXPOINTS = 10
JUNKWORDS={"trouble":6,"solution":5,"charge":3,"virus":7}
fil = open("filnamne.txt", "r")

foundwords = {}

points = 0

for word in fil.read().split():
   if word in JUNKWORDS:
       if word not in foundwords:
           foundwords[word] = 0
       points += JUNKWORDS[word]
       foundwords[word] += 1

if points > 10:
    print "SPAM"
    for word in foundwords:
        print word, foundwords[word]*JUNKWORDS[word]
else:
    print "The file doesn't contain any junk"

您可能希望在单词上使用.lower() 并将所有字典键设为小写。也许还可以删除所有非字母数字字符。

【讨论】:

  • has_key 已经被弃用了很长时间,取而代之的是 word in JUNKWORDS
  • 酷,我会做出改变的。旧习惯很难改掉;-)
  • @Hoopdady set() 是做什么的?
  • 它声明了一个集合。集合只是维护唯一事物列表的一种快速方法。这是我如何跟上文件中找到的唯一垃圾词列表的方式。如果您不希望它是唯一的,只需将其更改为 foundwords = [] 以使其成为列表,foundwords.append(word) 以添加单词。
  • @Hoopdady,哦,我明白了。但是,如果我的字典中的单词在文件中多次出现怎么办?
【解决方案2】:

这是另一种方法:

from collections import Counter

word_points = {'trouble': 6, 'solution': 5, 'charge': 3, 'virus': 7}

words = []

with open('ham.txt') as f:
   for line in f:
      if line.strip(): # weed out empty lines
         for word in line.split():
             words.append(word)

count_of_words = Counter(words)

total_points = {}
for word in word_points:
    if word in count_of_words:
       total_points[word] = word_points[word] * count_of_words[word]

if sum(i[0] for i in total_points.iteritems()) > 10:
   print 'SPAM {}'.format(sum(i[0] for i in total_points.iteritems()))
   for i in total_points.iteritems():
      print 'Word: {} Points: {}'.format(*i)

您可以进行一些优化,但它应该让您对一般逻辑有所了解。 Counter 适用于 Python 2.7 及更高版本。

【讨论】:

  • “清除空行”也将由line.split() 完成,因此整个循环就是words = [w for ln in f for w in ln.split()]
  • @Burhan Khalid 'dict' 对象没有属性 'iteritems'
  • 您必须使用 Python 3,只需将其替换为 items(),如 total_points.items(),您应该将 print 'Word: {} Points: {}'.format(*i) 更改为 print('Word: {} Points: {}'.format(*i))
【解决方案3】:

我假设每个单词都有不同的点,所以我使用了dictionary
您需要找出单词中的单词在文件中出现的次数。
您应该将每个单词的点存储为整数。不像'6p''4p'

那么,试试这个:

def find_junk(filename):
    word_points = {"trouble":6,"solution":3,"charge":2,"virus":4}
    word_count = {word:0 for word in word_points}
    count = 0
    found = []
    with open(filename) as f:
        for line in f:
            line = line.lower()
            for word in word_points:
                c = line.count(word)
                if c > 0:
                    count += c * word_points[word]
                    found.append(word)
                    word_count[word] += c
    if count >= 10:
        print '  SPAM'*4
        for word in found:
            print '%10s%3s%3s' % (word, word_points[word], word_count[word])
    else:
        print "Not spam"
find_junk('spam.txt')

【讨论】:

  • 所以这是低效的,因为它循环遍历每行的单词点。随着 word_points 的增长,这将变得不那么有效。
  • 这不是唯一的方法,遍历file 中的每个单词,junkwords 中的每个单词...我更喜欢junkwords
  • 当您执行for word in word_points 时,您将失去字典的一步查找功能。您将浏览大量不在文件中的 word_points 中的单词。所以最好只遍历文件中的每个单词,看看它是否在字典中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 2010-10-16
  • 2014-02-25
  • 2013-09-07
  • 1970-01-01
  • 2010-10-10
相关资源
最近更新 更多