Python 优化:选择字典还是列表的列表

3
我是新手Python3开发者,我有一个关于解决问题的不同方法的问题,涉及使用不同的数据结构。我的问题是如何比较不同采样技术之间的权衡。在我的程序中,我首先使用字典数据结构来解决这个问题。然后我尝试只使用列表数据结构来重写它。我尝试考虑排序的好处,但我无法确定两种方法之间的区别。似乎两种方法之间并没有太大的区别。
方法1:我使用字典创建直方图键和值对。
方法2:它接受字符串格式的源文本,并返回一个由列表组成的列表,其中每个子列表的第一个元素是单词,第二个元素是它在源文本中的频率。
# This program Analyze word frequency in a histogram
# sample words according to their observed frequencies
# takes in a source text in string format and returns a dictionary
# in which each key is a unique word and its value is that word's
# frequency in the source text
import sys
import re
import random
import time

def histogram(source_text):
    histogram = {}
    # removing any sort of string, removing any other special character
    for word in source_text.split():
        word = re.sub('[.,:;!-[]?', '', word)

        if word in histogram:
            histogram[word] += 1
        else:
            histogram[word] = 1
    return histogram

def random_word(histogram):
    probability = 0
    rand_index = random.randint(1, sum(histogram.values()))
    # Algorithm 1
    for (key, value) in histogram.items():
        for num in range(1, value + 1):
            if probability == rand_index:
                if key in outcome_gram:
                    outcome_gram[key] += 1
                else:
                    outcome_gram[key] = 1
                # return outcome_gram
                return key
            else:
                probability += 1

#    Method 2 takes in a source text in string format and returns a list #of lists
#    in which the first element in each sublist is the word and the #second element is its frequency in the source texts

  # Algorithm 2
    # for word in histogram:
    #     probability += histogram[word]
    #     if probability >= rand_index:
    #         if word in outcome_gram:
    #             outcome_gram[word] += 1
    #         else:
    #             outcome_gram[word] = 1
            # return word


if __name__ == "__main__":
    outcome_gram = {}
    dict = open('./fish.txt', 'r')
    text = dict.read()
    dict.close()

    hist_dict = histogram(text)
    for number in range(1, 100000):
        random_word(hist_dict)

5
早期优化是万恶之源......先衡量,再修剪......我建议使用最可读的版本,也就是 collections.Counter(my_text_corpus) - Joran Beasley
谢谢您的建议。我很感激这个建议。 - DataEngineer
2个回答

5
哪个更易读?我认为字典版本更容易理解。此外,请注意,您可以将第二种方法返回的2元组列表传递给dict构造函数,以重现第一种方法的输出。这应该给您一个大致相等的想法,除非这会导致性能问题,否则不必过于担心。
Python的优势在于您可以用五行代码以可读的方式编写相同的代码。
import re, random
from collections import Counter

def histogram(text):
    clean_text = re.sub('[.,:;!-[]?', '', text)
    words = clean_text.split()
    return Counter(words)

def random_word(histogram):
    words, frequencies = zip(*histogram.items())
    return random.choices(words, frequencies, k=1)

非常清晰......(尽管我会在整个文本上运行清理器,而不是逐个单词运行)Counter(cleaner(text)) - Joran Beasley
@joran 如果我没记错的话,对整个字符串使用Counter会计算所有字母的数量,而不是单词的数量。 - Jared Goguen
Counter(cleaner(text).split()) 对不起,你是对的 :P ... 但是与其清理每个单词,不如一次清理整个语料库。 - Joran Beasley
1
@JoranBeasley,你说得很好,我已经相应地进行了更新。 - Jared Goguen

2
我基本上同意Joran Beasley上面的评论,通常最好先解决你的问题,然后再回头重构以提高效率。
当使用直方图时,我建议查看集合模块中的Counter。整个集合模块非常好用,有很多有用的容器。
另一个很酷的模块是Timeit模块,它允许你在代码片段上运行小型计时实验。请记住,执行速度取决于许多因素,并不一定在程序的控制范围内。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接