【问题标题】:Frequency of keywords in a list列表中关键字的频率
【发布时间】:2017-05-23 07:37:41
【问题描述】:

嗨,所以我有 2 个文本文件,我必须阅读第一个文本文件,计算每个单词的频率并删除重复项,并创建一个包含单词及其在文件中的计数的列表。

我的第二个文本文件包含关键字,我需要计算这些关键字在第一个文本文件中出现的频率,并在不使用任何导入、dict 或 zip 的情况下返回结果。

我被困在如何进行第二部分我打开文件并删除了标点符号等,但我不知道如何找到频率 我玩弄了.find() 的想法,但目前还没有运气。

任何建议将不胜感激,这是我目前的代码似乎在关键字文件中找到关键字的频率,但在第一个文本文件中没有找到

def calculateFrequenciesTest(aString):

   listKeywords= aString
   listSize = len(listKeywords)
   keywordCountList = []

   while listSize > 0:
      targetWord = listKeywords [0]
      count =0
      for i in range(0,listSize):
         if targetWord == listKeywords [i]:
            count = count +1

      wordAndCount = []
      wordAndCount.append(targetWord)
      wordAndCount.append(count)

      keywordCountList.append(wordAndCount)

      for i in range (0,count):
         listKeywords.remove(targetWord)
      listSize = len(listKeywords)

   sortedFrequencyList = readKeywords(keywordCountList)

   return keywordCountList;

编辑-目前正在考虑再次重新打开我的第一个文件的想法,但这次没有将其变成列表?我认为我的错误以某种方式来自它计算我的列表列表的频率。这些是我得到的结果类型

[[['the', 66], 1], [['of', 32], 1], [['and', 27], 1], [['a', 23], 1], [['i', 23], 1]]

【问题讨论】:

  • 您可以做的是,遍历您的每个关键字,如果该关键字存在于您的 frequency list 中,则只需在该索引处增加它。
  • 这基本上是我想做的,但我尝试了几种不同的方法,但没有成功:s

标签: python python-3.x jes


【解决方案1】:

你可以试试这样的:

我以单词列表为例。

word_list = ['hello', 'world', 'test', 'hello']
frequency_list = {}
for word in word_list:
    if word not in frequency_list:
        frequency_list[word] = 1
    else:
        frequency_list[word] += 1
print(frequency_list)

RESULT: {'test': 1, 'world': 1, 'hello': 2}

由于您对 dicts 进行了限制,因此我使用了两个列表来完成相同的任务。我不确定它的效率如何,但它可以达到目的。

word_list = ['hello', 'world', 'test', 'hello']
frequency_list = []
frequency_word = []
for word in word_list:
    if word not in frequency_word:
        frequency_word.append(word)
        frequency_list.append(1)
    else:
        ind = frequency_word.index(word)
        frequency_list[ind] += 1

print(frequency_word)
print(frequency_list)

RESULT : ['hello', 'world', 'test']
         [2, 1, 1]

您可以将其更改为您喜欢的方式或根据需要重新考虑它

【讨论】:

【解决方案2】:

我同意@bereal 的观点,您应该为此使用Counter。我看到您说过您不想要“导入、字典或压缩”,因此请随意忽略此答案。然而,Python 的主要优势之一是其出色的标准库,每次你有list 可用时,你也会有dictcollections.Counterre

从您的代码中,我得到的印象是您希望使用与 C 或 Java 相同的样式。我建议尝试多一点pythonic。以这种方式编写的代码可能看起来不熟悉,并且需要时间来适应。然而,你会学到更多。

阐明你想要达到的目标会有所帮助。你在学习 Python 吗?你在解决这个特定的问题吗?为什么不能使用任何 import、dict 或 zip?

所以这是一个利用内置功能(没有第三方)的建议(使用 Python 2 测试):

#!/usr/bin/python

import re           # String matching
import collections  # collections.Counter basically solves your problem


def loadwords(s):
    """Find the words in a long string.

    Words are separated by whitespace. Typical signs are ignored.

    """
    return (s
            .replace(".", " ")
            .replace(",", " ")
            .replace("!", " ")
            .replace("?", " ")
            .lower()).split()


def loadwords_re(s):
    """Find the words in a long string.

    Words are separated by whitespace. Only characters and ' are allowed in strings.

    """
    return (re.sub(r"[^a-z']", " ", s.lower())
            .split())


# You may want to read this from a file instead
sourcefile_words = loadwords_re("""this is a sentence. This is another sentence.
Let's write many sentences here.
Here comes another sentence.
And another one.
In English, we use plenty of "a" and "the". A whole lot, actually.
""")

# Sets are really fast for answering the question: "is this element in the set?"
# You may want to read this from a file instead
keywords = set(loadwords_re("""
of and a i the
"""))

# Count for every word in sourcefile_words, ignoring your keywords
wordcount_all = collections.Counter(sourcefile_words)

# Lookup word counts like this (Counter is a dictionary)
count_this = wordcount_all["this"] # returns 2
count_a = wordcount_all["a"] # returns 1

# Only look for words in the keywords-set
wordcount_keywords = collections.Counter(word
                                         for word in sourcefile_words
                                         if word in keywords)

count_and = wordcount_keywords["and"] # Returns 2
all_counted_keywords = wordcount_keywords.keys() # Returns ['a', 'and', 'the', 'of']

【讨论】:

    【解决方案3】:

    这是一个没有导入的解决方案。它使用嵌套线性搜索,在小输入数组上进行少量搜索是可以接受的,但在输入较大时会变得笨拙和缓慢。

    这里的输入仍然很大,但它会在合理的时间内处理它。我怀疑如果您的关键字文件较大(我的只有 3 个字),就会开始显示减速。

    这里我们获取一个输入文件,遍历行并删除标点符号,然后用空格分割并将所有单词展平到一个列表中。该列表有欺骗,所以要删除它们,我们对列表进行排序,以便欺骗聚集在一起,然后对其进行迭代,创建一个包含字符串和计数的新列表。我们可以通过在列表中出现相同单词时增加计数并在看到新单词时移动到新条目来做到这一点。

    现在您有了词频列表,您可以在其中搜索所需的关键字并检索计数。

    输入文本文件是here,关键字文件可以由文件中的几个单词拼凑而成,每行一个。

    python 3 代码,在适用的地方指明如何为 python 2 修改。

    # use string.punctuation if you are somehow allowed 
    # to import the string module.
    translator = str.maketrans('', '', '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~')
    
    words = []
    with open('hamlet.txt') as f:
        for line in f:
            if line:
                line = line.translate(translator)
                # py 2 alternative
                #line = line.translate(None, string.punctuation)
                words.extend(line.strip().split())
    
    # sort the word list, so instances of the same word are
    # contiguous in the list and can be counted together
    words.sort()
    
    thisword = ''
    counts = []
    
    # for each word in the list add to the count as long as the 
    # word does not change
    for w in words:
        if w != thisword:
            counts.append([w, 1])
            thisword = w
        else:
            counts[-1][1] += 1
    
    for c in counts:
        print('%s (%d)' % (c[0], c[1]))
    
    # function to prevent need to break out of nested loop
    def findword(clist, word):
        for c in clist:
            if c[0] == word:
                return c[1]
        return 0   
    
    # open keywords file and search for each word in the 
    # frequency list.
    with open('keywords.txt') as f2:
        for line in f2:
            if line:
                word = line.strip()
                thiscount = findword(counts, word)
                print('keyword %s appear %d times in source' % (word, thiscount))
    

    如果您愿意,您可以修改findword 以使用二分搜索,但它仍然不会接近dictcollections.Counter 是没有限制的正确解决方案。它的代码更快,代码更少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-16
      • 1970-01-01
      相关资源
      最近更新 更多