读取文本文件以按降序打印字母频率python3

2024-04-28 22:33:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做python基本挑战这是其中之一。我所要做的就是通读一个文件,然后按降序打印出字母的频率。我能做到这一点,但我想通过打印出频率百分比和字母-频率-频率%来增强程序。像这样:o - 46 - 10.15%

这就是我目前所做的:

def exercise11():
    import string
    while True:
        try:
            fname = input('Enter the file name -> ')
            fop = open(fname)
            break
        except:
            print('This file does not exists. Please try again!')
            continue

    counts = {}
    for line in fop:
        line = line.translate(str.maketrans('', '', string.punctuation))
        line = line.translate(str.maketrans('', '', string.whitespace))
        line = line.translate(str.maketrans('', '', string.digits))
        line = line.lower()
        for ltr in line:
            if ltr in counts:
                counts[ltr] += 1
            else:
                counts[ltr] = 1
    lst = []
    countlst = []
    freqlst = []
    for ltrs, c in counts.items():
        lst.append((c, ltrs))
        countlst.append(c)
    totalcount = sum(countlst)
    for ec in countlst:
        efreq = (ec/totalcount) * 100
        freqlst.append(efreq)
    freqlst.sort(reverse=True)
    lst.sort(reverse=True)
    for ltrs, c, in lst:
        print(c, '-', ltrs)

exercise11()

如您所见,我可以计算并排序不同列表上的freq%,但我无法将其与字母freq一起包含在lst[]列表的元组中。有什么方法可以解决这个问题吗?在

如果你对我的代码有任何其他建议的话。请务必提及。 Output Screen


修改

应用@wwii I提到的一个简单的修改就得到了期望的输出。我所要做的就是在迭代lst[]列表时向print语句再添加一个参数。以前,我尝试为freq%,sort创建另一个列表,然后尝试将其插入到列表中的letters count tuple中,但没有成功。在

^{pr2}$

Output Screen


Tags: intrue列表forstring字母linetranslate
3条回答

元组是不可变的,这可能是您正在发现的问题。另一个简单的函数是更高级的。见下文:

元组列表格式为lst,但是由于元组是不可变的,而列表是可变的,所以选择将lst更改为列表列表是一种有效的方法。然后,由于lst是一个列表列表,每个元素都由'letter,count,frequency%'组成,所以带有lambda的排序函数可以用来根据您想要的任何索引进行排序。以下内容将插入for line in fop:循环之后。在

lst = []
for ltrs, c in counts.items():
    lst.append([ltrs,c])
totalcount = sum([x[1] for x in lst])       # sum all 'count' values in a list comprehension

for elem in lst:
    elem.append((elem[1]/totalcount)*100)   # now that each element in 'lst' is a mutable list, you can append the calculated frequency to the respective element in lst

lst.sort(reverse=True,key=lambda lst:lst[2])    # sort in-place in reverse order by index 2.

freqlstcountlist和{}中的项通过它们的位置相互关联。如果有任何排序,则关系将丢失。在

在排序之前将列表压缩在一起可以保持这种关系。在

将从您的列表初始化行中提取。在

lst = []
countlst = []
freqlst = []
for ltr, c in counts.items():
    #change here, lst now only contains letters
    lst.append(ltr)
    countlst.append(c)
totalcount = sum(countlst)
for ec in countlst:
    efreq = (ec/totalcount) * 100
    freqlst.append(efreq)

#New stuff here: Note this only works in python 3+
zipped = zip(lst, countlst, freqlst)
zipped = sorted(zipped, key=lambda x: x[1])

for ltr, c, freq in zipped:
    print("{} - {} - {}%".format(ltr, c, freq)) # love me the format method :)

基本上,zip将列表组合成一个元组列表。然后可以使用lambda函数对这些元组进行排序(非常常见的堆栈问题)

您的计数数据在{letter:count}对的字典中。在

您可以使用字典按如下方式计算总数:

total_count = sum(counts.values())

那么在你迭代计数之前不要计算百分比。。。在

^{pr2}$

或者,如果你想把它们都列在一个列表中,这样就可以对它们进行排序:

data = []
for letter, count in counts.items():
    data.append((letter,count,100*count/total)

使用operator.itemgetter作为排序键函数可以帮助代码的可读性。在

import operator
letter = operator.itemgetter(0)
count = operator.itemgetter(1)
frequency = operator.itemgetter(2)

data.sort(key=letter)
data.sort(key=count)
data.sort(key=frequency)

相关问题 更多 >