最大子数组之和2
本篇博客主要内容为编写一个函数求一个二维数组中的最大连续子数组之和(即最大矩阵),并对该代码进行单元测试和代码覆盖率测试。
一、编写代码求最大子数组之和
1、存储二维数组的txt文件截图

2、定义函数求最大子数组
2.1、第一个函数,用于读取文本的总行数
def count_Line(filepath): # 该函数用于获取文本文件的行数 with open(filepath, 'r', encoding='UTF8') as f: count_line = 0 # 存储文本文件的行数 while True: # 获取文本文件的行数 line = f.readline() if not line: break count_line += 1 return count_line
此函数的作用是判断文件是否读取到了最后一行。
2.2、第二个函数,用于指定读取文件的某一行
1 def readline(filepath, lineNum): 2 # 函数参数:参数1:文件路径;参数2:将要读取的行号 3 # 用于读取文本文件的每一行,并将其数据存入一个数组中,并返回数组 4 # 文本文件的数据格式如下: 5 ''' 6 ①数据为二维数组,且全为整数 7 ②文件第一行为数组行数,第二行为数组列数,第三行即以后为二维数组 8 ③数据之间用中文或英文逗号隔开 9 ''' 10 with open(filepath, 'r', encoding='UTF8') as f: 11 count_line = count_Line(filepath) 12 # 存储文本文件的行数 13 if lineNum == count_line: 14 # 判断是否读取到了文件的最后一行 15 out = f.readlines()[lineNum - 1] 16 else: 17 out = f.readlines()[lineNum - 1][0:-1] 18 # 读取文件,并读取指定行 19 str_row = '' 20 # 用于将每一行中分隔起来的每一个有效数据保存 21 num = [] 22 # 用于存入有效数据 23 count = 0 24 # 用于记录数据是否读取完毕 25 judge = [',', ','] 26 # 判断分隔符用 27 for x in out: 28 count += 1 29 if x not in judge: 30 str_row += x 31 # 将需要的数据提取出来(’连续的数字‘ 或 ’负号加连续的数字‘) 32 elif x in judge: 33 num.append(str_row) 34 str_row = '' 35 # 将分隔符前的实数放入数组 num 中 36 if count == len(out): 37 num.append(str_row) 38 str_row = '' 39 # 将最后一个数据也放入数组 num 中 40 if '' in num: 41 num.remove('') 42 # 去掉数组中的空元素 43 num = list(map(int, num)) 44 # 将字符串数组转换成整型数组 45 return num
第13行到17行要判断是否读取到了文件末尾的原因是会有 ‘\n’ 转义字符的干扰。(除最后一行外,其余行读取时,在其末尾都有此转义字符)
2.3、第三个函数,用于将文件中第三行到最后的该二维数组存储起来
def doubleArray(filepath): # 该函数用于将上述文本文件中的二维数组存储起来 outLine_1 = readline(filepath, 1) num_douArray = [] for x in range(outLine_1[0]): num_douArray.append(readline(filepath, x+3)) return num_douArray
此函数返回的是一个二维列表。
2.4、第四个函数,用于得出所有的子数组
def getAllNumSons(filepath, num): # 此函数用来获取二维列表的所有连续子数组,并将其存放进一个列表中 # 此函数获得的所有连续子数组均为二维列表形式 # 使用此函数得先行导入 pandas 和 numpy # 导入形式:import pandas as pd # import numpy as np data = pd.DataFrame(num) # 将 num 转换成 DataFrame 数据形式 NUM =[] # 用来存放所有的连续子数组 for x in range(readline(filepath, 2)[0]): # x 用来指定从哪一行开始截取原二维数组 for y in range(readline(filepath, 1)[0] + 1): # y 用来指定到哪一行结束截取原二维数组 if len(data[x:y]) != 0: # 判断是否有空的数据 data_1 = data[x:y] # 将截取的数据赋值给 data_1 for i in range(readline(filepath, 2)[0]): # i 用来指定从哪一列开始截取 data_1 for j in range(readline(filepath, 2)[0] + 1): # j 用来指定到哪一列结束截取 data_1 if len(list(data_1.iloc[:, i:j])) != 0: # 判断是否有空值 data_array = np.array(data_1.iloc[:, i:j]) # 将 DataFrame 转换成 array # data_array.tolist(): 将 array 转换成二维列表 NUM.append(data_array.tolist()) # 将这个子数组放入 NUM 中 return NUM
此函数中得出的每一个子数组的存储形式也是二维列表,即该函数返回的是存储了大量二维列表的列表。
2.5、第五个函数,用于得出最大子数组之和与最大子数组
def outPut(filepath): # 此函数的参数为文本文件的路径 num = doubleArray(filepath) NUM = getAllNumSons(filepath, num) numSum = [] # 用来存放每个子数组的和 for x in NUM: numSum.append(sum(map(sum, x))) # sum(map(sum, x)): 此方法用来求和二维列表,因为每个子数组都是以二维列表形式存放的 return max(numSum), NUM[numSum.index(max(numSum))] # 返回最大子数组之和 和 最大子数组
此函数返回最大子数组之和与最大子数组
2.6、以上函数处理该文件的结果

2.7、对该函数进行验证正确性
新文件如下:

运行结果如下:

老师给的结果:

二、对代码进行单元测试
单元测试使用unittest。
1、单元测试代码
import unittest class Test(unittest.TestCase): def test_outPut1(self): self.assertEqual(outPut(filepath1), (28, [[-3, 8], [20, 0], [-3, 6]])) def test_outPut2(self): self.assertEqual(outPut(filepath2), (964, [[9, 12, -9, -2, 23], [201, -1, 309, 3, 6], [100, 21, 292, -2, 2]])) if __name__ == "__main__": unittest.main()
2、运行结果

三、对代码进行覆盖率测试
覆盖率测试使用coverage。
1、在cmd命令行执行命令coverage run 文件名.py

测试通过。
2、在cmd命令行执行命令coverage report查看代码覆盖率

可以看到覆盖率为100%。
3、在cmd命令行执行命令coverage html -d covTest
-d 后面为将要生成的文件的文件名,可随意取名。

3.1、可以看到在执行命令后,我们的文件目录下生成了一个名为 covTest 的文件夹。

3.2、其中有两个html文件,双击在浏览器打开查看。
index.html内容如下:

main_py.html内容如下:

四、未彻底解决的问题
如果是将程序代码和单元测试代码分在两个.py文件中,并在单元测试文件中导入了程序代码文件中的函数后,在cmd命令中执行“coverage run 文件名”命令时会报错。如下:

这种报错情况暂时未找到较好的解决方法,若此刻读到本博客的您了解的话,希望不吝赐教,抱拳。
浙公网安备 33010602011771号