Python 在txt中从字典中搜索单词并返回值 我的函数应该在文本中从字典中查找单词,然后在“points”变量中一起添加值。

Python 在txt中从字典中搜索单词并返回值 我的函数应该在文本中从字典中查找单词,然后在“points”变量中一起添加值。,python,python-3.x,function,dictionary,Python,Python 3.x,Function,Dictionary,但我把事情搞砸了。我的过程如下: 字典: words = {'very funny': 3,'funny': 2,'accidentally funny': 1} 文本文件(名为:sample.txt): 巨蟒很有趣+3 有些站姿很有趣+2 政客有时会意外地变得滑稽可笑+1 真正的蟒蛇一点也不好笑+二, *这些值表示我希望为每一行获得的分数 从.txt文件中获取文本: with open('sample.txt', 'r') as text: data = text.read(

但我把事情搞砸了。我的过程如下:

  • 字典:

    words = {'very funny': 3,'funny': 2,'accidentally funny': 1}  
    
  • 文本文件(名为:sample.txt):

  • 巨蟒很有趣+3
    有些站姿很有趣+2
    政客有时会意外地变得滑稽可笑+1
    真正的蟒蛇一点也不好笑+二,

    *这些值表示我希望为每一行获得的分数

  • 从.txt文件中获取文本:

    with open('sample.txt', 'r') as text:
        data = text.read()
    
  • 功能:

    def counter(data): #this should find keywords
        default_value = 0 #var for stuff not included in dict
        points = 0 
        for i in data:
            points += words.get(i, default_value)  #using get to avoid valueError
        print(points)
        return points  
    
    counter(data)
    
  • 输出:

    0  
    
    Process finished with exit code 0
    
  • 编辑我知道我忘了什么;]:

    问题
  • 我的功能似乎仍然不重要
  • 我想用一种方式给那些关键的磨损评分,使单个单词“搞笑”不会被三重评分,而只触发
    “搞笑”:2
    效果。不过我不知道该怎么做

  • 这是我关于堆栈的第一个问题,所以如果我把事情搞砸了,请告诉我。

    对于数据中的I
    ,这就是问题所在。由于数据是一个
    str
    ,您基本上是在遍历单个字符,而不是完整的单词。

    我建议您反转您的逻辑-遍历术语并计算它们出现的次数:

    def counter(data): #this should find keywords
        points = 0 
        for word, value in words.items():
            points += value * data.count(word)
        print(points)
        return points  
    
    然而,这意味着一些术语可以得分不止一次——
    “非常有趣”
    也包含
    “有趣”
    ,所以它应该值5分(3分来自
    “非常有趣”
    ,2分来自
    “有趣”


    您的文本包含4个
    有趣
    、1个
    非常有趣
    和1个
    意外有趣
    ,因此结果是4*2+3+1=12

    这里的问题是您的数据结构。一般来说,如果你想查字典,字典是好的。然而,这不是你在这里要做的。相反,我建议使用一个元组列表。因此,您的
    单词将如下所示:

    words = [ ("very funny", 3), ("funny", 2), ("accidentally funny", 1) ]
    
    splitData = data.split(' \r\n')
    total = 0
    for i in range(0, len(splitData)):
    
        # Longest entry in words has two words so we use i + 2
        phrase = ' '.join(splitData[i:(i + 2)])
        if (phrase in words):
            total += words[phrase]
    
    接下来,当您运行for循环时,您将迭代字符串中的每个字符,而不是每个单词。您应该做的是迭代
    单词中的值,并找到每个单词出现的次数:

    import re
    
    total = 0
    for w in words:
        total += w[1] * sum(re.finditer(w[0], data))
    
    然而,正如已经指出的那样,这将发现重复。为了避免这种情况,您应该按照要搜索的顺序排列
    单词
    ,并删除从
    数据中找到的值

    words = [ ("very funny", 3), ("accidentally funny", 1), ("funny", 2) ]
    
    total = 0
    for w in words:
        total += len(list(re.finditer(w[0], data))) * w[1]
        data = data.replace(w[0], '')
    
    然而,这并不是很有效。如果你想让它跑得更快,我会使用一个。基本上,您可以将数据拆分为空白,并对其进行迭代,提取下一个
    k
    字符,其中
    k
    words
    中最长条目中的字数。您可以使用空格将这些
    k
    单词连接在一起,并检查它们是否匹配
    words
    中的任何条目。在这种情况下,顺便说一句,你可能想用字典。你可以这样做:

    words = [ ("very funny", 3), ("funny", 2), ("accidentally funny", 1) ]
    
    splitData = data.split(' \r\n')
    total = 0
    for i in range(0, len(splitData)):
    
        # Longest entry in words has two words so we use i + 2
        phrase = ' '.join(splitData[i:(i + 2)])
        if (phrase in words):
            total += words[phrase]
    
    当然,这个解决方案假设所有条目中都有两个单词,但事实并非如此。要解决此问题,请将
    单词
    编入词典词典,其中顶级词典将短语映射到其包含的单词数:

    words = {1: {"funny": 2}, 2: {"very funny": 3, "accidentally funny": 1}}
    splitData = data.split(' \r\n')
    total = 0
    i = 0
    while (i < len(splitData)):
        for l, mapping in words.items():
            phrase = ' '.join(splitData[i:(i + l)])
            if (phrase in mapping):
                total += mapping[phrase]
                i += 1
                continue
        i++
    
    words={1:{“有趣”:2},2:{“非常有趣”:3,“意外有趣”:1}
    splitData=data.split('\r\n')
    总数=0
    i=0
    而(i

    请注意,我将
    l
    添加到
    I
    ,以避免重复。同样,您可以使用元组而不是字典来声明搜索顺序。另外,我在这里使用while循环而不是forloop,因为在Python中,实际上无法更改循环中循环不变量的值。

    这就是我要做的。我把这篇文章分成一个单词列表,然后在上面迭代。我将每个单词与前面的一个连接起来。然后在字典里查两个单词的东西。当然,我不能将第一个单词与它前面的单词连接起来。所以first_iteration变量只在第一次迭代时为true,在第一次迭代结束时变为false,变为false。 我希望这能解决你的问题

    def counter(data): #this should find keywords
        default_value = 0 #var for stuff not included in dict
        points = 0 
        first_iteration = True
        wordsList = data.split()
        for i in wordList:
            if (!first_iteration):
                theWord = i + " " + prev
            points += words.get(theWord, default_value)  #using get to avoid valueError
            prev = i
            first_iteration = False
        print(points)
        return points  
    
    counter(data)
    

    因为第一个问题是一个很好的解释:你输入的预期输出是什么?@Austin我希望第一行的分数是+3,第二行的分数是+2,第三行的分数是+1,第四行的分数是+2=8是的,问题是我想把它从“非常有趣”和“意外有趣”中分离出来,算作一个“有趣”的单独数字。我应该在邮件里写。很快就会编辑的。看起来不错!我会尽快试试这个。谢谢你一步一步地解释。这很有帮助。@noobcodes如果这个解决方案有帮助,我建议使用upvoting。不只是对我来说,但总的来说。我会尽快检查它,一旦我得到15个代表。我们新手在那之前不能投票@noobcodes我还建议在你想列为问题“解决方案”的答案上打勾。不一定是我的,但这有助于其他用户在将来查看您的问题:)在介绍LL解析器之前的部分中,我得到以下信息:
    total+=len(re.finditer(w[0],data))*w[1]
    TypeError:type'callable\u iterator'的对象没有len()