要学习的知识点
- 列表、字典、集合、元组的区别
- 字典键值与频次统计
- 集合成员判断与去重
- 列表保留首次出现顺序
- 可变与不可变容器
题目
练习 4:用字典统计整数频次,并按首次出现顺序输出不同整数。
输入:第一行 n,第二行 n 个整数(空格分隔)。
完整代码
以下内容与 ex04.py 一致,可对照右侧讲解阅读。
"""练习 4:用字典统计整数频次,并按首次出现顺序输出不同整数。
输入:第一行 n,第二行 n 个整数(空格分隔)。
学习说明:
- split() 把输入行拆成数字文本;for 循环逐个转换为整数并保存到列表。
- tuple(values) 把列表转换为不可修改的元组。
- frequencies 字典保存“整数 -> 出现次数”;用 if/else 判断键是否存在,再更新次数。
- seen 集合检查数字是否见过;unique_in_order 列表按首次出现顺序保存不同数字。
- 最后分别输出频次、不同数字和元组。
"""
n = int(input())
value_texts = input().split()
values = []
for index in range(n):
value_text = value_texts[index]
value = int(value_text)
values.append(value)
values_tuple = tuple(values)
frequencies = {}
seen = set()
unique_in_order = []
for value in values:
if value in frequencies:
frequencies[value] = frequencies[value] + 1
else:
frequencies[value] = 1
if value not in seen:
seen.add(value)
unique_in_order.append(value)
print("frequencies:")
for value, count in frequencies.items():
print(value, count)
print("unique:")
for value in unique_in_order:
print(value)
print("tuple:", values_tuple)
进阶写法
这版与初学版解决同一道题,写法更精炼。先读代码,再看下面的简要说明。
进阶源码文件:ex04_adv.py
"""练习 4 进阶版:用 map、切片、字典 get 和星号解包简化步骤。"""
n = int(input())
values = list(map(int, input().split()))[:n]
values_tuple = tuple(values)
frequencies = {}
seen = set()
unique_in_order = []
for value in values:
frequencies[value] = frequencies.get(value, 0) + 1
if value not in seen:
seen.add(value)
unique_in_order.append(value)
print("frequencies:")
for value, count in frequencies.items():
print(value, count)
print("unique:", *unique_in_order)
print("tuple:", values_tuple)
list(map(...)) 先把数字文本转换并保存成列表,[:n] 取前 n 项;dict.get(value, 0) 表示键不存在时先当作 0,再加一;print(..., *unique_in_order) 用星号把列表中的值逐个传给 print。
运行结果
示例输入:
6
4 2 4 1 2 4程序输出:
frequencies:
4 3
2 2
1 1
unique:
4
2
1
tuple: (4, 2, 4, 1, 2, 4)逐个认识函数
下面只列出本程序实际用到的写法;先看参数如何传入,再看返回值怎样保存或输出。
| 函数/写法 | 功能与返回值 | 注意事项 |
|---|---|---|
input() | 读取一行并返回字符串。 | 本题读取元素数量和数字文本行。 |
str.split() | 按空白拆分字符串,返回文本列表。 | 循环中再逐个转换为整数。 |
int(text) | 把整数文本转换为整数。 | 每次只转换一个数字。 |
range(n) | 产生 n 个下标:0 到 n-1。 | 本题用它依次读取 n 个输入项。 |
list.append(value) | 在列表末尾追加一个值;返回 None。 | 将转换后的整数保存到 values。 |
tuple(values) | 从可迭代对象创建元组。 | 元组的元素序列不能被修改。 |
set() / set.add(value) | 创建集合 / 向集合添加元素。 | 集合用于判断数字是否见过,不用来保持输出顺序。 |
dict.items() | 提供字典中的键值对供循环遍历。 | 可写成 for key, value in frequencies.items()。 |
print(...) | 输出对象;返回 None。 | 不同数字逐行输出,避免星号解包。 |
三种容器的分工
| 类型 | 适合做什么 | 本题中的变量 |
|---|---|---|
| list 列表 | 有顺序、可修改、允许重复。 | values 保存输入;unique_in_order 按发现顺序保存不重复数。 |
| dict 字典 | 用键查值;键唯一。现代 Python 字典保持插入顺序。 | frequencies 将数字映射到出现次数。 |
| set 集合 | 元素唯一,可快速判断成员关系;不承诺适合展示的顺序。 | seen 只回答“这个数以前见过吗”。 |
| tuple 元组 | 有顺序、允许重复,但创建后不能增删改元素。 | values_tuple 保存输入序列的固定版本。 |
输入与字典计数
输入行通过 split() 拆成文本,再用循环逐项 int() 转成整数。更新频次时先判断 value 是否已经是 frequencies 的键:如果有就加一;如果没有,就把次数设成一。
if value in frequencies:
frequencies[value] = frequencies[value] + 1
else:
frequencies[value] = 1这和 get() 的快捷写法效果相同,但把“第一次出现”和“再次出现”分开写出来了。
算法流程:数一次、记一次
- 每读到一个 value,字典里的计数在旧值基础上加 1。
- 用
value not in seen判断首次出现。not 是逻辑“非”。 - 首次出现就同时加入集合和顺序列表。集合负责查重,列表负责保序,两者不能互相替代。
- 遍历字典显示计数,再显示唯一列表和元组。
如果直接把集合打印出来,顺序不适合作为题目答案的一部分。要保序去重,就像本程序一样同时使用 set 和 list。
代码如何运行
- 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
- 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
- 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。
先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。
自己动手试一试
测试所有数都相同、所有数都不同;观察字典顺序与集合用途的区别。
先在 lx04.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。