实验3:列表、元组的应用
1. 查找最大元素的索引
编写函数 indicesOfLargestElement(list),输入整数列表list, 返回 list 中最大元素所有的索引,索引以列表形式返回。
例子:
IndexOfLargestElement([2, 1, 3, 1, 3]) # return [2,4]
(1)具体思路
通过max函数获取列表中的最大值,并通过循环在列表中查找,如果当前值等于最大值,则将下标存入列表中。
(2)编程实现
# 定义函数
def IndexOfLargestElement(list):
return [i for i, a in enumerate(list) if a == max(list)]
# 主函数
temp = []
print("Please input numbers to end with -1:")
# 循环获取输出
while True:
a = eval(input())
if a == -1:
break
temp.append(a)
# 进行输出
print(IndexOfLargestElement(temp))
函数部分通过enumerate()对列表进行遍历,并通过max函数获取列表中的最大值,并通过循环在列表中查找,如果当前值等于最大值,则将下标存入列表中。
主函数部分先定义空列表,使用while循环读入数字并以-1结束,若输入值为-1则break出循环,若不为-1则存入列表中。完成列表元素读入后调用函数并输出。
(3)运行并测试
①开始运行程序,将提示输入数字并以-1结尾:
②完成输入后即输出结果:
2. 合并两个排序的列表
编写函数 merge(list1, list2),将两个排序好的整数列表合并到一个新的排序列表中,返回这个新的列表。
使用两种方法实现 merge 函数:
不使用 sort() 或 sorted();
使用 sort() 或 sorted()。
例子:
merge([2, 4, 7], [1,5,6]) # return [1, 2, 4, 5, 6, 7]
(1)具体思路
a.不使用 sort() 或 sorted()
分别通过变量记录两列表的第一个数字,比较两数大小,将较小的存入结果列表中并将该索引值加一,再次进行比较。按照以上规律一直循环操作下去,直至一列表中全部数字存入结果列表时,将另一列表中所有元素再依次存入结果列表。
b.使用 sort() 或 sorted()
通过’+’将两个列表合并后直接调用sort进行排序并输出。
(2)编程实现
# 使用sort进行排序
def merge_with_sort(list1, list2):
res = list1+list2
res.sort()
return res
# 不使用sort进行排序
def merge_without_sort(list1, list2):
# 定义两列表初始索引
i = 0
j = 0
res = []
# 依次访问两序列进行排序
while i < len(list1) and j < len(list2):
# 比较当前索引大小
if list1[i] < list2[j]:
res.append(list1[i])
i = i+1
else:
res.append(list2[j])
j = j+1
# 如果序列一未完全放入结果序列中
if i < len(list1):
res.append(list1[i])
i = i+1
# 如果序列二未完全放入结果序列中
if j < len(list2):
res.append(list2[j])
j = j+1
return res
# 主函数
temp1 = []
temp2 = []
# 循环获取输入
print("Please input numbers into the first list end with -1:")
while True:
a = eval(input())
if a == -1:
break
temp1.append(a)
print("Please input numbers into the second list end with -1:")
while True:
a = eval(input())
if a == -1:
break
temp2.append(a)
# 输出结果
print(merge_with_sort(temp1, temp2))
print(merge_without_sort(temp1, temp2))
使用sort进行排序的函数通过先将两列表合并后,再利用sort进行排序。不使用sort进行排序的函数则先定义两列表的初始索引,指向列表的第一个元素。比较两列表当前索引值,将较小值存入结果列表并将索引值加一。依次循环至任一列表为空。则将另一不为空列表全部按顺序放入结果列表并返回。
主函数中通过依次获得两个列表的输入完成两列表的输入,并分别调用两函数以输出结果。
(3)运行并测试
①运行程序后将提示依次输出两列表的值并以-1结尾
②完成输入后即输出两个相同的排序结果:
3. 子列表
编写函数 match_pattern(list1, list2),仅当 list2 是 list1 的子列表时返回 True。
例子:
list1 = [4, 10, 2, 3, 50, 100]
list2 = [3, 2, 50]
list3 = [2, 3, 50]
list4 = [2, 3, 40]
match_pattern(list1, list2) # return False
match_pattern(list1, list3) # return True
match_pattern(list1, list4) # return False
(1)基本思路
通过迭代器进行判断元素是否都在母列表中进行判断子列表。
(2)编程实现
# 判断函数
def match_pattern(list1, list2):
# 通过迭代器进行子序列判断
it = iter(list1)
return all(i in it for i in list2)
# 主函数
temp1 = []
temp2 = []
# 循环获取输入
print("Please input numbers into the first list end with -1:")
while True:
a = eval(input())
if a == -1:
break
temp1.append(a)
print("Please input numbers into the second list end with -1:")
while True:
a = eval(input())
if a == -1:
break
temp2.append(a)
# 输出结果
print(temp1)
print(temp2)
print(match_pattern(temp1, temp2))
先创建对应迭代器,再通过迭代器依次判断是否迭代器的每个元素都在母列表中。
主函数中通过依次获得两个列表的输入完成两列表的输入,并分别调用函数以输出结果。
(3)运行并测试
①运行程序后将提示依次输出两列表的值并以-1结尾,接下来依次进行三组测试。
a.存在反序元素
b.满足子序列:
c.存在不在母列表的元素:
4、模式识别-四个连续相等的数字
编写函数 isconsecurivefour(list1),用于测试列表 list1 中是否有四个连续相等的数字。编写测试程序,提示用户输入一系列整数,返回 True/False,表示是否包含四个连续相等的数字。
(1)基本思路
依次查找当前值是否与标记值相等,如果相等则计数器加一,如果不相等则计数器清零并查找下一个。直至将所有元素查找完毕,如果计数器在查找过程中存在等于4的时刻,则返回True,否则返回False。
(2)编程实现
# 定义函数
def isconsecurivefour(list1):
i = 0
flag = list1[0]
count = 0
# 依次查找
while i < len(list1):
# 如果一样,则计数器加一,下标加一
if flag == list1[i]:
count += 1
if count >= 4:
return True
i += 1
# 如果不一样则计数器清0并下标加一
else:
flag = list1[i]
i += 1
count = 1
# 如果遍历整个列表之后仍然找不到则返回False
return False
# 主函数
temp = []
print("Please input numbers to end with -1:")
# 循环获取输出
while True:
a = eval(input())
if a == -1:
break
temp.append(a)
# 进行输出
print(isconsecurivefour(temp))
定义i为下标值,flag为当前查找值,count为计数值。通过while对列表进行循环,并判断当前值与当前查找值是否相等,如果相等则计数加一,并下标自增1。如果不相等则将计数置为1,重置当前查找值,并将下标值加一进行下一次搜索。如果查找过程中计数值某刻大于等于4,则返回True。否则当遍历完整个列表后仍然未找到连续出现4次的元素,则返回False。
主函数中通过依次获得列表的输入,并调用函数以输出结果。
(3)运行并测试
①测试存在连续4个相同值的列表:
②测试不存在连续4个相同值的列表:
5. “几乎对称”列表
如果在一个非对称列表中,我们交换任意两个元素之后, 列表是对称的,则把这个列表称为“几乎对称”列表。例如,列表 lst=[1, 2, 1, 2] 是几乎对称的,因为交换 lst[2]和 lst[3]之后,得到对称的列表[1, 2, 2, 1]。编写函数 is_almost_symmetric(lst), 仅当列表 lst 是几乎对称列表时,返回 True。
(1)基本思路
首先判断是否为对称,如果直接为对称则直接返回False。如果不为对称则暴力穷举每一种可能的交换可能并判断是否为对称,如果可能则返回True,尝试了所有可能后如果仍然不可以则返回False。
(2)编程实现
# 定义判断是否是对称函数
def is_symmetric(list1):
# 从两端开始进行查找
i = 0
j = len(list1)-1
while i < j:
if list1[i] == list1[j]:
i += 1
j -= 1
else:
return False
return True
# 定义判断是否是几乎对称函数
def is_almost_symmetric(list1):
# 穷举每一种可能
for i in range(0, len(list1)-1):
for j in range(0, len(list1)-1):
listTemp = list1+[]
temp = listTemp[i]
listTemp[i] = listTemp[j]
listTemp[j] = temp
# 进行判断如果对称则返回True
if is_symmetric(listTemp):
return True
# 不对称则进行下一次穷举判断
return False
# 主函数
temp = []
print("Please input numbers to end with -1:")
# 循环获取输出
while True:
a = eval(input())
if a == -1:
break
temp.append(a)
# 进行输出
print((not is_symmetric(temp)) and is_almost_symmetric(temp))
首先定义判断是否对称函数,从列表头和尾各设置一下标,依次判断下标对应值是否相等,如果相等则头下标加一尾下标减一进行下一次判断,直至头下标大于等于尾下标。否则返回False。
再定义判断是否几乎对称函数,通过暴力穷举穷举每一种可能的交换情况,如果在某次交换下满足列表变为对称,则返回True。遍历所有可能后仍然找不到可能的交换方式的返回False。
主函数中通过依次获得列表的输入,并调用函数以输出结果。
(3)运行并测试
①如果输入对称列表,则返回False:
②如果输入列表为几乎对称列表,则返回True:
③如果输入列表既不对称也不几乎对称,则返回False:
6. 元组的理解
测试并回答以下问题:
(1)下面代码是否正确?解释原因。
t = (1, 2, 3)
t.append(4)
t.remove(0)
t[0] = 1
答:错误。因为元组不能被修改,故不能修改其中的元素值。
(2)下面代码是否正确?解释原因。
t1 = (1, 2, 3, 7, 9, 0, 5)
t2 = (1, 2, 5)
t1 = t2
答:正确。可以通过赋值运算符重新初始化元组。此时t1元组与t2元组都为(1,2,5)
(3)切片:测试下面代码,解释输出的结果。
t = (1, 2, 3, 7, 9, 0, 5)
①print(t[3])
输出:7
解释:切片下标为3(第4个)的元素,则输出元组中第四个元素的值。
②print(t[1: 3])
输出:(2, 3)
解释:切片下标从1到2的元素,则输出元组中第二、三个元素的值。
③print(t[-1:-3])
输出:()
解释:切片从倒数第1个到倒数第3个的元素,切片顺序反了,故输出空元组。
④print(t[-1:-3:-1])
输出:(5, 0)
解释:以步长-1切片从倒数第1个到倒数第2个的元素,故输出下标倒数第1个到倒数第2个组成的元组。
⑤print(t[-1: : -3])
输出:(5, 7, 1)
解释:以步长-3切片从倒数第1个到元组头的元素。故输出下标倒数第1个对应元素,下标倒数第1个下标减3对应元素和下标倒数第1个下标减6对应元素组成的元组。
⑥print(t[ : -1: 3])
输出:(1, 7)
解释:以步长3切片从第1个到最后1个前的元素。故输出下标0对应元素和下标0+3对应元素组成的元组。
⑦print(t[3 : -1: 3])
输出:(7,)
解释:以步长3切片从第4个到最后1个前的元素。故输出下标4对应元素组成的元组。
⑧print(t[3 : -1: -3])
输出:()
解释:以步长-3切片从第4个到最后1个前的元素。切片顺序反了,输出空元组。
实验心得
通过本次对列表和元组应用的学习,我学会了如何使用列表和元组完成对应的操作。列表和元组与C++中数组和vector容器类似,又不完全一样。Python中的元组提供了很丰富的切片方式,这是C++里所不具备的。本次实验中,我也学会了使用迭代器等对列表进行遍历等操作,熟悉了列表的相关函数,也夯实了Python的基本语法和编写函数的能力。这些都为我以后Python更深层次的学习打下了坚实基础。
本次实验中,也发现了比较值得注意的一点,列表不能使用“=”进行复制。通过“=”只能建立两个列表间的关联,修改一个,另外一个也会跟着修改,如果想要复制,可以利用切片或者合并操作完成复制。