轨道
/
Python
Python
/
练习
/
蒂斯伯里寻宝
蒂斯伯里寻宝

蒂斯伯里寻宝

学习练习

简介

在 Python 中,元组 是一个_不可变_的集合,其中的元素按_顺序_排列。 和大多数集合一样,tuples可以存放任何(或多种)数据类型,包括其他的tuples。 元组支持所有通用序列操作,但不支持可变序列操作。

元组的元素可以使用for item in <tuple>结构进行迭代。 如果同时需要元素的下标和值,可以使用for index, item in enumerate(<tuple>)。 和任何序列一样,tuples中的元素可以通过_方括号表示法_访问,使用从左数起的0-based index编号,或者从右数起的-1-based index编号。 元组也可以完整或部分地复制,使用切片表示法(<tuple>[<start>:<stop>:<step>])。

元组的构造

元组可以通过多种方式创建,既可以使用tuple(<iterable>)类构造函数,也可以使用tuple字面量声明。

以空参数或_可迭代对象_使用tuple()构造函数:

>>> no_elements = tuple()
()

# The constructor *requires* an iterable, so single elements must be passed in a list or another tuple.
>>> one_element = tuple([16])
(16,)

字符串是可迭代的,所以把单个str作为参数传给tuple()构造函数,可能会得到意想不到的结果:

# String elements (characters) are iterated through and added to the tuple
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')

传入单个可迭代对象时,它的元素会逐个被添加进去:

>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)

>>> multiple_elements_set = tuple({2, 3, 5, 7, 11})
(2,3,5,7,11)
将元组声明为_字面量_:

由于tuple(<iterable>)构造函数只接受_可迭代对象_(或不接受任何参数)作为参数,用字面量方法创建单元素元组要容易得多。

>>> no_elements = ()
()

>>> one_element = ("Guava",)
("Guava",)

嵌套的数据结构也可以作为tuple的元素,包括其他的tuples:

>>> nested_data_structures = ({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))

>>> nested_data_structures_1 = (["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
(["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))

元组的拼接

可以使用加号+运算符拼接元组,它会解包每个tuple,创建一个新的、合并后的tuple。

>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")

#likewise, using the multiplication operator * is the equivalent of using + n times
>>> first_group = ("cat", "dog", "elephant")

>>> multiplied_group = first_group * 3
('cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant')

访问元组中的元素

tuple中的元素可以通过_方括号表示法_访问,使用从左数起的0-based index编号,或者从右数起的-1-based index编号。

student_info = ("Alyssa", "grade 3", "female", 8 )

#gender is at index 2 or index -2
>>> student_gender = student_info[2]
'female'

>>> student_gender = student_info[-2]
'female'

#name is at index 0 or index -4
>>> student_name = student_info[0]
Alyssa

>>> student_name = student_info[-4]
Alyssa

迭代元组中的元素

tuple中的元素可以使用for item in <tuple>语法在循环中_迭代_。 如果同时需要下标和值,可以使用for index, item in enumerate(<tuple>)。

>>> student_info = ("Alyssa", "grade 3", "female", 8 )
>>> for item in student_info:
...   print(item)

...
Alyssa
grade 3
female
8

>>> for index, item in enumerate(student_info):
...  print("Index is: " + str(index) + ", value is: " + str(item) +".")

...
Index is: 0, value is: Alyssa.
Index is: 1, value is: grade 3.
Index is: 2, value is: female.
Index is: 3, value is: 8.

检查元组成员资格

可以使用in运算符检查某个元素是否在tuple中。

>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)

>>> "Parrot" in multiple_elements_list
True

说明

Azara 和 Rui 是队友,正在参加一场海盗主题的寻宝活动。 其中一人有一份附带地图坐标的宝藏清单,另一人有一份附带地图坐标的地点名称清单。 他们还拿到了几张空白地图,上面标着一个起点“你在这里”。


Azara 的清单 Rui 的清单
Treasure Coordinates
Amethyst Octopus 1F
Angry Monkey Figurine 5B
Antique Glass Fishnet Float 3D
Brass Spyglass 4B
Carved Wooden Elephant 8C
Crystal Crab 6A
Glass Starfish 6D
Model Ship in Large Bottle 8A
Pirate Flag 7F
Robot Parrot 1C
Scrimshawed Whale Tooth 2A
Silver Seahorse 4E
Vintage Pirate Hat 7E
Location Name Coordinates Quadrant
Seaside Cottages ("1", "C") Blue
Aqua Lagoon (Island of Mystery) ("1", "F") Yellow
Deserted Docks ("2", "A") Blue
Spiky Rocks ("3", "D") Yellow
Abandoned Lighthouse ("4", "B") Blue
Hidden Spring (Island of Mystery) ("4", "E") Yellow
Stormy Breakwater ("5", "B") Purple
Old Schooner ("6", "A") Purple
Tangled Seaweed Patch ("6", "D") Orange
Quiet Inlet (Island of Mystery) ("7", "E") Orange
Windswept Hilltop (Island of Mystery) ("7", "F") Orange
Harbor Managers Office ("8", "A") Purple
Foggy Seacave ("8", "C") Purple

不过情况有点乱:Azara 的坐标在格式和排序上似乎都和 Rui 的不一样,他们得不停地在两份清单之间来回查看,才能弄清楚哪些宝藏对应哪些地点。 作为初出茅庐的 Python 爱好者,他们来找你帮忙写一个小程序(其实是一组函数),好把寻宝信息整理得更有条理。

1. 提取坐标

实现get_coordinate()函数,它接收 Azara 清单中的一个(treasure, coordinate)对,只返回提取出来的地图坐标。

>>> get_coordinate(('Scrimshawed Whale Tooth', '2A'))
2A

2. 格式化坐标

实现convert_coordinate()函数,它接收“2A”这种格式的坐标,返回("2", "A")这种格式的元组。

>>> convert_coordinate("2A")
("2", "A")

3. 匹配坐标

实现compare_records()函数,它接收一个(treasure, coordinate)对和一个(location, coordinate, quadrant)记录,并比较两者的坐标。 如果坐标“匹配”,返回 True;如果不匹配,返回 False。 为了准确比较,按需重新格式化坐标。

>>> compare_records(('Brass Spyglass', '4B'), ('Seaside Cottages', ('1', 'C'), 'blue'))
False

>>> compare_records(('Model Ship in Large Bottle', '8A'), ('Harbor Managers Office', ('8', 'A'), 'purple'))
True

4. 合并匹配的记录

实现create_record()函数,它接收 Azara 清单中的一个(treasure, coordinate)对和 Rui 清单中的一个(location, coordinate, quadrant)记录,如果坐标匹配,就返回(treasure, coordinate, location, coordinate, quadrant)。 如果坐标_不_匹配,返回字符串 "not a match"。 为了准确比较,按需重新格式化坐标。

>>> create_record(('Brass Spyglass', '4B'), ('Abandoned Lighthouse', ('4', 'B'), 'Blue'))
('Brass Spyglass', '4B', 'Abandoned Lighthouse', ('4', 'B'), 'Blue')

>>> create_record(('Brass Spyglass', '4B'), ('Seaside Cottages', ('1', 'C'), 'blue'))
"not a match"

5. “清理”并生成所有记录的报表

清理 Azara 和 Rui 合并后的记录,让每条记录只剩下一组坐标。再生成一份报表,这样他们就能在一份清单里看到需要标到地图上的所有内容。 实现clean_up()函数,它接收一个元组的元组(来自两份清单的全部内容),遍历_外层_元组,从每个_内层_元组中去掉多余的坐标,再把每一条都添加到一个“报表”里。 格式化并返回这个“报表”,让每一行上有一条清理好的记录。

>>> clean_up((('Brass Spyglass', '4B', 'Abandoned Lighthouse', ('4', 'B'), 'Blue'), ('Vintage Pirate Hat', '7E', 'Quiet Inlet (Island of Mystery)', ('7', 'E'), 'Orange'), ('Crystal Crab', '6A', 'Old Schooner', ('6', 'A'), 'Purple')))

"""
('Brass Spyglass', 'Abandoned Lighthouse', ('4', 'B'), 'Blue')\n
('Vintage Pirate Hat', 'Quiet Inlet (Island of Mystery)', ('7', 'E'), 'Orange')\n
('Crystal Crab', 'Old Schooner', ('6', 'A'), 'Purple')\n
"""
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Python Exercism

准备好开始 蒂斯伯里寻宝 了吗?

注册 Exercism,借助 17 个概念146 个练习 和真人导师指导,学习并掌握 Python,全部免费。