背景:在解决一些编程问题中如棋盘的初始化,链表,队列的构建;数据处理中如用SAS软件输入数据等涉及到矩阵的概念,而用编程语言实现矩阵的方式有C中的数组,python中的列表等。现在给你一个数据如下,或者是你从某个excel表中copy下来的数据,打开idea创建一个变量excel把该数据赋值给它,然后我们该如何把这种字符串数据矩阵进行转置呢?
excel='''
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
0 0 2 2 4 4 5 6 6 7 -4 -2 -3 -3 -5 1 0 0 -1 -1 -3
6 5 5 3 4 3 1 2 1 0 3 2 2 0 2 1 -1 -2 -1 -3 -5
'''
目录
一、矩阵的输入、输出和转化
二、矩阵转置
三、矩阵的运算
四、矩阵计算器GUI界面
在这之前,我们先介绍下矩阵的输入、输出和一维列表和二维列表之间的转化:
1、创建和输入实现:
l=[list(map(int,input().split())) for i in range(0,int(input()))]
print(l)
row=int(input('输入行数:'))
col=int(input('输入列数:'))
l=[[int(input()) for j in range(0,col)] for i in range(0,row)]
print(l)
结果:
你可以看见对于第一种输入一般是不带有交互信息的,比较适合蓝桥杯等比赛题目的数据输入处理,这种输入对矩阵的列数是不限制的,也就是你输入的可以不是一个方阵。
第二种输入是带有交互信息的,但它的每行只能输入一个数据,所以不太适合处理已给定的数据,但它的行列是限制好的,可以在这个基础上避免人为的输入其他形式的矩阵。
把输入的input改为空字符串,就相当于创建一个空元素的矩阵了,进行赋值可以实现其他要求。
2、输出实现:
有输入自然离不开输出,这里的输出不是直接print(l)了,因为我们的目的是输出矩阵的面貌,而不是列表,列表只是一个桥梁工具。就像后面列表的转置过程,你不能把转置好的列表来打印,而是遍历该列表,print打印出数学上矩阵的格式。
row=int(input('输入行数:'))
col=int(input('输入列数:'))
l=[[int(input()) for j in range(0,col)] for i in range(0,row)]
for i in range(row):
for j in range(col):
print(l[i][j],end=' ')
print()
结果:
3、互相转化实现:
l=[1,2,3,4,5,6,7,8,9]
row=int(input('输入转化的行数:'))
col=int(input('输入转化的列数:'))
new_l=[l[i:i+col] for i in range(0,row*col,col)]
print(new_l)
new_l=[str(j) for i in new_l for j in i]
new_l=' '.join(new_l)
print(new_l)
显然,这里漏了一种情况就是自己转化自己的时候可能会有点逻辑上的问题,但并不影响后面的转置打印,只是对有些题目或者矩阵运算的设计起到了点干扰。到这里你就知道了这个转化是把开头背景中提到的excel字符串数据矩阵进行转置的重要步骤了,它连接了字符串到一维列表进而连接到二维列表,接下来就是对二维列表进行转置操作了。
既然要对已知的矩阵进行转置,那么我们的已知信息就是该矩阵的行数和列数,这是我们实现转置的关键切入口。
excel='''
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
0 0 2 2 4 4 5 6 6 7 -4 -2 -3 -3 -5 1 0 0 -1 -1 -3
6 5 5 3 4 3 1 2 1 0 3 2 2 0 2 1 -1 -2 -1 -3 -5
'''
def change(excel:str):
r,c=3,21
excel=excel.split()
excel=[excel[i:i+c] for i in range(0,len(excel),c)]
New_excel=[[excel[j][i] for j in range(0,r)] for i in range(0,c)]
#[['' for j in range(0,r)] for i in range(0,c)]
for i in range(c):
for j in range(r):
print(New_excel[i][j],end=' ')
print()
change(excel)
显然这里是创建了一个新的列表矩阵,该列表里面的元素是空字符串,随便遍历新旧列表中的其中一个,对换他们的行数和列数就实现了装置,当然当矩阵为方阵的时候可以不创建列表,遍历它自己i=j的时候元素不变,其他情况进行变量值交换。(上面的方法更新了下,你可以思考下区别)
结果:
1、加法和减法:
def sum(l1,l2):
r,c=3,3
l3=[[(l1[i][j]+l2[i][j]) for j in range(c)] for i in range(r)]
#l3=[[(l1[i][j]-l2[i][j]) for j in range(c)] for i in range(r)]
print(l3)
l1=[[9,9,9],[9,9,9],[9,9,9]]
l2=[[1,1,1],[1,1,1],[1,1,1]]
sum(l1,l2)
结果:
因为涉及到后面gui界面的设计,这里不探讨行数为1或者列数为1的细节问题。矩阵的加法和减法的要求是两个矩阵要行列数相同,所以gui设计的时候要加上判断条件。
2、乘法:
def mul(l1,l2):
r1,c1=2,3
r2,c2=3,2
if r2!=c1:
print('矩阵不是同一类型!')
l3=[[0 for j in range(c2)] for i in range(r1)]
for i in range(r1):
for j in range(c2):
for k in range(c1):
l3[i][j]+=l1[i][k]*l2[k][j]
print(l3)
l1=[[9,9,9],[9,9,9]]
l2=[[1,1],[1,1],[1,1]]
mul(l1,l2)
结果:
这里难的点在于多加了一层循环,而对于矩阵乘法运算规则来说,这层循环满足了l1的行变化与l2的列变化同步,在最后一层循环中,k充当了连接条件。
实现思路:当我们把数据组copy下来的时候,放在输入框内输入,这个时候的数据就是一个字符串,显然我们第一步要把字符串用split方法变为一个一维列表。得到一维列表后,我们需要的是该矩阵本身的关键数据:行数和列数,同样在输入框内输入,你可以设计两个输入框,可以用一个输入框加上split方法得到该数据信息。同样的,加减乘的运算就是三个按钮和多一个输入框输入另一个矩阵,最后加上一个输出框得到结果信息,同时你也可以考虑分两个界面来做。
from tkinter import *
class Change():
global r,c
global r1,c1
def __init__(self):
root = Tk() # 创建主体窗口
root.title('行列转换') # 定义窗体的名字
root.geometry('700x500') # 定义窗体的初始大小
root.maxsize(1200, 1200) # 设置窗口可以显示的最大尺寸
label1 = Label(root, text="输入矩阵1的行和列数:", bg='Aquamarine')
label1.grid(row=0,column=0) # side,bg,fg,width=20,height=20,justify="right",font=("微软雅黑",20)
E_var1 = StringVar()
entry1 = Entry(root, textvariable=E_var1)
entry1.grid(row=0,column=1)
def Getcr():
global r,c
r,c=map(int,E_var1.get().split())
text1.insert(END, f'已输入行数{r},已输入列数{c}。\n')
button1=Button(root,text="确定", bg='Aquamarine',command=Getcr)
button1.grid(row=0,column=2)
label2 = Label(root, text="输入矩阵1内容:", bg='Aquamarine')
label2.grid(row=1,column=0) # side,bg,fg,width=20,height=20,justify="right",font=("微软雅黑",20)
E_var2 = StringVar()
entry2 = Entry(root, textvariable=E_var2)
entry2.grid(row=1,column=1)
def change():
global r,c
excel=E_var2.get()
text1.insert(END,'输入矩阵:\n')
excel=excel.split()
excel=[excel[i:i+c] for i in range(0,len(excel),c)]
for i in range(r):
for j in range(c):
text1.insert(END,excel[i][j]+' ')
text1.insert(END,'\n')
New_excel=[['' for j in range(0,r)] for i in range(0,c)]
text1.insert(END,'转置矩阵格式1:\n')
for i in range(c):
for j in range(r):
New_excel[i][j]=excel[j][i]
text1.insert(END,New_excel[i][j]+' ')
text1.insert(END,'\n')
New_excel=[j for i in New_excel for j in i]
New_excel=' '.join(New_excel)
text1.insert(END,'转置矩阵格式2:'+'\n'+New_excel+ '\n')
button2 = Button(root, text="行列转置", bg='Aquamarine', command=change)
button2.grid(row=1, column=2)
label3 = Label(root, text="输入矩阵2的行和列数:", bg='Aquamarine')
label3.grid(row=2,column=0) # side,bg,fg,width=20,height=20,justify="right",font=("微软雅黑",20)
E_var3= StringVar()
entry3 = Entry(root, textvariable=E_var3)
entry3.grid(row=2,column=1)
def Getcr1():
global r1,c1
r1,c1=map(int,E_var3.get().split())
text1.insert(END, f'已输入行数{r1},已输入列数{c1}。\n')
button3=Button(root,text="确定", bg='Aquamarine',command=Getcr1)
button3.grid(row=2,column=2)
label4 = Label(root, text="输入矩阵2内容:", bg='Aquamarine')
label4.grid(row=3,column=0) # side,bg,fg,width=20,height=20,justify="right",font=("微软雅黑",20)
E_var4 = StringVar()
entry4 = Entry(root, textvariable=E_var4)
entry4.grid(row=3,column=1)
def count1():
global r,c,r1,c1
excel=E_var2.get()
text1.insert(END,'输入矩阵1:\n')
excel=excel.split()
excel=[excel[i:i+c] for i in range(0,len(excel),c)]
for i in range(r):
for j in range(c):
text1.insert(END,excel[i][j]+' ')
text1.insert(END,'\n')
excel1=E_var4.get()
text1.insert(END,'输入矩阵2:\n')
excel1=excel1.split()
excel1=[excel1[i:i+c] for i in range(0,len(excel1),c)]
for i in range(r1):
for j in range(c1):
text1.insert(END,excel1[i][j]+' ')
text1.insert(END,'\n')
sum_excel=[[str((int(excel[i][j])+int(excel1[i][j]))) for j in range(c)] for i in range(r)]
text1.insert(END,'矩阵相加结果::\n')
for i in range(r):
for j in range(c):
text1.insert(END,sum_excel[i][j]+' ')
text1.insert(END,'\n')
def count2():
global r,c,r1,c1
excel=E_var2.get()
text1.insert(END,'输入矩阵1:\n')
excel=excel.split()
excel=[excel[i:i+c] for i in range(0,len(excel),c)]
for i in range(r):
for j in range(c):
text1.insert(END,excel[i][j]+' ')
text1.insert(END,'\n')
excel1=E_var4.get()
text1.insert(END,'输入矩阵2:\n')
excel1=excel1.split()
excel1=[excel1[i:i+c1] for i in range(0,len(excel1),c1)]
for i in range(r1):
for j in range(c1):
text1.insert(END,excel1[i][j]+' ')
text1.insert(END,'\n')
mul_excel=[[0 for j in range(c1)] for i in range(r)]
for i in range(r):
for j in range(c1):
for k in range(c):
mul_excel[i][j]+=int(excel[i][k])*int(excel1[k][j])
text1.insert(END,'矩阵相乘结果::\n')
for i in range(r):
for j in range(c1):
text1.insert(END,str(mul_excel[i][j])+' ')
text1.insert(END,'\n')
button5 = Button(root, text="矩阵相加", bg='Aquamarine', command=count1)
button5.grid(row=3, column=2)
button6 = Button(root, text="矩阵相乘", bg='Aquamarine', command=count2)
button6.grid(row=3, column=3)
text1 = Text(root, state="normal",width=80,heigh=40)
text1.grid(row=4, columnspan=10)
root.mainloop()
if __name__ == '__main__':
Change()
实现结果:
当然,你会发现上面的gui界面少了很多按钮逻辑的提示警告,这里丰富GUI界面的内容笔者不再进行扩充,内容开源,希望各位大佬不吝赐教!