本章为深入字符串的操作,题目大多是处理文件中的数据
此题是给了一个内有多年天然气数据的txt文件,读取文件,然后得出
1. 年平均价格
2. 生成含有价格排序的文件
这个是初始txt文件,我这里简化至只保留了三个年份共六行数据
12-27-1993:0.999
12-27-1993:0.992
01-03-1994:0.992
01-10-1994:0.995
01-02-1995:1.127
01-09-1995:1.134
第一问:
这里我一开始想过把他们都填入一个列表,再切片处理,把年份和价格分开再计算。也想过用字典计算。但是都在怎么把前后相同年份放一起计算那里出了问题,用if a[i]==a[i+1] 的方法总是会长度溢出列表。最后借鉴了github上yorwosa的代码GitHub - yorwosa/starting-out-with-python-global-4th-edition: Exercises for the book Starting out with Python 4th edition.通过一个中间变量year来解决。下面是思路:
year = ''
for i in range(len(a)):
if year == '':
year = a[i]
............
elif a[i]==year:
............
else:
year = a[i]
首先第一项是第一年,进行一次操作,然后i++。若下一年和上一年一样,则继续进行操作;若不一样则把这个不一样的年份作为新的year。
不过我在运行yorwosa的代码的时候发现总是无法输出最后一个年份,然后我发现他的逻辑是每当找到下一个不同年份时才会把前一组年份数据填入列表,所以导致最后一个年份没有下一个了也就不会执行填入列表操作。所以我做了一点改进,单独把最后一年的数据填入列表,然后就可以全部输出了。以下是第一问代码:
def average_price_per_year(dates, prices):
# data_list=['12-06-1993', '12-27-1993', '01-03-1994', '08-15-1994', '12-18-1995', '12-25-1995']
# price_list=['1.036', '0.999', '0.992', '1.161', '1.124', '1.128']
year = ''
counter = 0
accumulator = 0
average_year_years = []
average_year_prices = []
for index in range(len(dates)): # index=[0,1,2,3,4]
# 第一年
if year == '':
year = dates[index][6:10] # 第一年是data_list这个列表里[0]位置'12-06-1993'的[6:10]切割位置
accumulator += float(prices[index]) # 价格的和
counter += 1 # 计数一共是几年
elif dates[index][6:10] == year: # 如果下一年和上一年相同
accumulator += float(prices[index]) # 继续计算价格和
counter += 1 # 继续计数一共几年
else: # 如果下一年和上一年不同
average = accumulator / counter # 计算平均价格
average_year_years.append(year) # 年份列表填入列表,此时year是最后一个与上一年相同年份的年
average_year_prices.append(average) # 把本年平均价格填入列表
year = dates[index][6:10] # 然后这个与最后一个year不同的dates[index][6:10]成为“新的一年”
counter = 1 # 此时不用从第一个循环if year == ''开始,所以counter直接从1开始计数
accumulator = float(prices[index]) # 新的 “第一年”的价格也开始进入价格总和的计算
if index == len(dates) - 1: # 之前是没有这一步的,若没有,则循环进行到最后一年时,因为没有“与上一年不同的年份,所以不会进行第22行的过程,也不会进行最后一年的计算和填入”
average = accumulator / counter
average_year_years.append(year)
average_year_prices.append(average)
print('年平均价格:')
print('----------------------')
print('Year\tPrice')
print('----\t-----')
for index in range(len(average_year_years)): # 此时相同年份已经合并,直接看有多少年就输出多少就行
print(average_year_years[index], ':', format(average_year_prices[index], ',.3f'))
if __name__ == '__main__':
infile = open('text.txt', 'r')
infile_list = infile.readlines() # infile_list = ['12-06-1993:1.036\n', '12-27-1993:0.999\n'…………]
date_list = []
price_lists = []
# data_list ['12-06-1993', '12-27-1993', '01-03-1994', '08-15-1994', '12-18-1995', '12-25-1995']
# price_list ['1.036', '0.999', '0.992', '1.161', '1.124', '1.128']
for line in infile_list: # 对于infile_list的每一项
date_list.append(line[0:10]) # [0:10]是年份,切片后填入date列表
price_lists.append(line[11:].rstrip('\n')) # [11:]是价格,切片并去除换行符后填入price列表
infile.close()
average_price_per_year(date_list, price_lists)
第二问:
第二问我看了yorwosa的代码不过输出的时候只能输出排序后的数字,而前面的日期全成了一样的了,所以这里我直接用的自己的方法。
因为不太懂如何在排完序后输出时前面的日期也能对应输出,最后了解了lambda匿名函数和sorted的按key排序方法才解决这个问题
def sor_of_prices():
file = open('text.txt', 'r')
a = file.readline()
c = []
while a != '':
a = a.rstrip('\n')
b = ''.join(a).split(':') # 逐行读取,并把每一行数据按照冒号分为时间和价格
# print(b)
c.append(b) # 把每一组时间和价格都填入c列表
a = file.readline()
# print(c)
L1 = sorted(c, key=lambda x: eval(x[1]), reverse=True) # 用到了lambda匿名函数来规定排序依据是价格
# print(L1)
outfile = open('LowToHigh.txt', 'w')
print("价格排序:")
print('----------------------')
for i in L1:
res = ':'.join(i) # 此时L1的每一项都是['01-09-1995','1.134']的形式,所以对于每一项里面每一个小项用冒号连接为字符串
print(res)
outfile.write(res + '\n')
outfile.close()
if __name__ == '__main__':
sor_of_prices()
下面是运行结果:
生成的txt文件: