MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python在字典中存储列表的实战技巧

2021-08-053.6k 阅读

Python 在字典中存储列表的基础概念

字典与列表的特性回顾

在深入探讨在字典中存储列表的技巧之前,先简单回顾一下 Python 中字典(dict)和列表(list)的基本特性。

字典是一种无序的键值对集合,其中键必须是唯一且不可变的,而值可以是任意类型,包括列表。字典的主要优势在于通过键快速查找对应的值,时间复杂度平均为 O(1)。例如:

my_dict = {'name': 'Alice', 'age': 30}
print(my_dict['name'])  

这里通过键 'name' 可以迅速获取到值 'Alice'

列表是一种有序的可变序列,可以容纳不同类型的元素。列表支持通过索引访问元素,索引从 0 开始。例如:

my_list = [10, 'apple', True]
print(my_list[1])  

这里通过索引 1 获取到值 'apple'

在字典中存储列表的结构

当在字典中存储列表时,我们构建了一种复合数据结构。此时,字典的某个值是一个列表对象。例如:

data_dict = {
    'fruits': ['apple', 'banana', 'cherry'],
    'numbers': [1, 2, 3]
}

在这个 data_dict 中,键 'fruits' 对应的值是一个水果名称的列表,键 'numbers' 对应的值是一个数字列表。这种结构在很多实际场景中非常有用,比如存储不同类别的数据集合。

向字典中的列表添加元素

直接使用列表方法

向字典中列表添加元素最直接的方式就是使用列表自身的方法,比如 append()extend() 等。假设我们有一个字典,其中存储了不同班级学生的名字列表:

class_students = {
    'class1': ['Alice', 'Bob'],
    'class2': ['Charlie', 'David']
}
# 向 class1 班级添加一个学生
class_students['class1'].append('Eve')
print(class_students)

上述代码中,通过 class_students['class1'].append('Eve')class1 对应的列表添加了一个新元素 'Eve'

如果要一次添加多个元素,可以使用 extend() 方法。例如:

new_students = ['Frank', 'Grace']
class_students['class2'].extend(new_students)
print(class_students)

这里通过 extend() 方法将 new_students 列表中的所有元素添加到了 class2 对应的列表中。

根据条件动态添加

在实际应用中,可能需要根据某些条件向字典中的列表添加元素。比如,我们有一个字典存储不同颜色的物品列表,现在要根据物品的颜色将新物品添加到对应的列表中:

color_items = {
   'red': ['apple', 'ball'],
    'blue': ['pen', 'book']
}
new_item = 'cup'
item_color = 'blue'
if item_color in color_items:
    color_items[item_color].append(new_item)
else:
    color_items[item_color] = [new_item]
print(color_items)

这段代码首先检查物品的颜色是否已经在字典的键中。如果存在,则将新物品添加到对应颜色的列表中;如果不存在,则创建一个新的键值对,值为包含新物品的列表。

从字典中的列表删除元素

根据元素值删除

从字典中的列表删除元素可以使用列表的 remove() 方法。假设我们有一个字典存储不同城市的景点列表,现在要删除某个景点:

city_attractions = {
    'Beijing': ['The Great Wall', 'Forbidden City', 'Summer Palace'],
    'Shanghai': ['Oriental Pearl Tower', 'The Bund']
}
attraction_to_remove = 'Forbidden City'
if 'Beijing' in city_attractions:
    attractions = city_attractions['Beijing']
    if attraction_to_remove in attractions:
        attractions.remove(attraction_to_remove)
print(city_attractions)

这里先检查城市 'Beijing' 是否在字典中,然后检查景点 'Forbidden City' 是否在该城市的景点列表中,如果都满足则使用 remove() 方法删除该景点。

根据索引删除

除了根据元素值删除,还可以根据索引删除列表中的元素,使用 pop() 方法。例如,在存储不同类型文件的字典中,要删除某个文件类型列表中的特定文件(通过索引):

file_types = {
    'documents': ['report.doc', 'presentation.pptx', 'letter.txt'],
    'images': ['photo1.jpg', 'photo2.png']
}
file_index = 1
if 'documents' in file_types:
    files = file_types['documents']
    if len(files) > file_index:
        files.pop(file_index)
print(file_types)

这段代码检查 'documents' 键是否存在于字典中,并且列表长度是否大于要删除的索引。如果条件满足,则使用 pop() 方法删除指定索引位置的文件。

访问字典中列表的元素

单层访问

访问字典中列表的元素相对简单,先通过字典的键获取到列表,然后再通过列表的索引获取具体元素。例如,有一个字典存储不同月份的销售数据列表:

sales_data = {
    'January': [100, 150, 120],
    'February': [90, 110, 100]
}
# 获取 January 的第二个销售数据
january_second_sale = sales_data['January'][1]
print(january_second_sale)

这里通过 sales_data['January'] 获取到 'January' 对应的列表,再通过 [1] 获取列表中索引为 1 的元素。

多层嵌套访问

在更复杂的场景中,可能会遇到字典中列表元素又是一个字典或其他复合结构的情况。例如,有一个字典存储不同部门的员工信息,员工信息以字典形式存储在列表中:

company_departments = {
    'HR': [
        {'name': 'Tom', 'age': 28, 'position': 'HR Specialist'},
        {'name': 'Jane', 'age': 32, 'position': 'HR Manager'}
    ],
    'Engineering': [
        {'name': 'John', 'age': 30, 'position': 'Software Engineer'},
        {'name': 'Alice', 'age': 29, 'position': 'QA Engineer'}
    ]
}
# 获取 HR 部门第一个员工的职位
hr_first_employee_position = company_departments['HR'][0]['position']
print(hr_first_employee_position)

这里先通过 company_departments['HR'] 获取到 'HR' 部门的员工信息列表,再通过 [0] 获取列表中的第一个员工信息字典,最后通过 ['position'] 获取该员工的职位。

对字典中列表进行统计与分析

计算列表长度

在处理字典中列表时,经常需要知道列表中元素的数量,即列表长度。可以使用 Python 的内置函数 len()。例如,统计不同课程的学生人数:

course_students = {
    'Math': ['Alice', 'Bob', 'Charlie'],
    'Science': ['David', 'Eve']
}
math_student_count = len(course_students['Math'])
science_student_count = len(course_students['Science'])
print(f"Math 课程学生人数: {math_student_count}")
print(f"Science 课程学生人数: {science_student_count}")

这里通过 len() 函数分别计算了 'Math''Science' 课程对应的学生列表长度。

统计列表中元素出现次数

有时需要统计列表中某个元素出现的次数。比如,在一个字典存储不同颜色球的列表中,统计某种颜色球的数量:

color_balls = {
   'red': ['ball1','ball2','ball3','ball4','ball5'],
    'blue': ['ball6','ball7','ball8']
}
red_ball_count = color_balls['red'].count('ball1')
print(f"红色球 'ball1' 的数量: {red_ball_count}")

这里通过列表的 count() 方法统计了 'red' 颜色列表中 'ball1' 出现的次数。

求列表元素总和、平均值等

对于存储数值的列表,可能需要计算其总和、平均值等统计量。例如,有一个字典存储不同小组的成绩列表:

group_scores = {
    'group1': [85, 90, 95],
    'group2': [70, 75, 80]
}
group1_total = sum(group_scores['group1'])
group1_average = group1_total / len(group_scores['group1'])
print(f"小组 1 的总成绩: {group1_total}")
print(f"小组 1 的平均成绩: {group1_average}")

这里使用 sum() 函数计算了 'group1' 成绩列表的总和,再通过总和除以列表长度得到平均值。

字典中列表的排序

对列表本身排序

可以直接对字典中列表进行排序,使用列表的 sort() 方法。例如,有一个字典存储不同城市的温度列表,对每个城市的温度列表进行升序排序:

city_temperatures = {
    'Beijing': [25, 23, 27],
    'Shanghai': [28, 26, 29]
}
for city, temperatures in city_temperatures.items():
    temperatures.sort()
print(city_temperatures)

这里通过 for 循环遍历字典的每个键值对,对每个城市对应的温度列表使用 sort() 方法进行升序排序。

根据列表中元素的某个属性排序(针对列表元素为字典的情况)

当字典中的列表元素是字典时,可能需要根据字典的某个键进行排序。比如,有一个字典存储不同员工的信息列表,员工信息以字典形式存储,现在要根据员工年龄对列表进行排序:

company_employees = {
    'department1': [
        {'name': 'Tom', 'age': 28},
        {'name': 'Jane', 'age': 32}
    ],
    'department2': [
        {'name': 'John', 'age': 30},
        {'name': 'Alice', 'age': 29}
    ]
}
for department, employees in company_employees.items():
    employees.sort(key=lambda x: x['age'])
print(company_employees)

这里使用 sort() 方法,并通过 key 参数指定一个匿名函数 lambda x: x['age'],表示根据字典中 'age' 键对应的值进行排序。

字典中列表的复制与深拷贝

浅拷贝

在处理字典中列表时,有时需要复制列表。如果使用简单的赋值操作,实际上是引用传递,而不是真正的复制。例如:

original_dict = {
    'numbers': [1, 2, 3]
}
new_dict = original_dict
new_dict['numbers'].append(4)
print(original_dict)  

这里 new_dictoriginal_dict 指向同一个字典对象,所以对 new_dict 中列表的修改会影响到 original_dict

要进行浅拷贝,可以使用字典的 copy() 方法或 copy 模块的 copy() 函数。例如:

import copy
original_dict = {
    'numbers': [1, 2, 3]
}
new_dict = original_dict.copy()
new_dict['numbers'].append(4)
print(original_dict)  
print(new_dict)  

这里通过 original_dict.copy() 进行了浅拷贝,new_dictoriginal_dict 是不同的字典对象,但它们内部的列表仍然是同一个对象,所以对 new_dict 中列表的修改会影响到 original_dict 中的列表。

深拷贝

如果要实现完全独立的复制,包括列表及其内部的所有元素,需要使用 copy 模块的 deepcopy() 函数。例如:

import copy
original_dict = {
    'nested_list': [[1, 2], [3, 4]]
}
new_dict = copy.deepcopy(original_dict)
new_dict['nested_list'][0].append(5)
print(original_dict)  
print(new_dict)  

这里通过 copy.deepcopy(original_dict) 进行了深拷贝,new_dictoriginal_dict 是完全独立的,对 new_dict 中嵌套列表的修改不会影响到 original_dict

字典中列表的序列化与反序列化

JSON 序列化

在很多应用场景中,需要将包含列表的字典数据存储到文件或通过网络传输。JSON(JavaScript Object Notation)是一种常用的数据交换格式。Python 的 json 模块可以方便地将字典(包括其中的列表)序列化为 JSON 格式的字符串,以及将 JSON 字符串反序列化为字典。例如:

import json
data_dict = {
    'fruits': ['apple', 'banana', 'cherry'],
    'numbers': [1, 2, 3]
}
# 序列化
json_data = json.dumps(data_dict)
print(json_data)
# 反序列化
new_dict = json.loads(json_data)
print(new_dict)

这里通过 json.dumps() 方法将字典 data_dict 序列化为 JSON 字符串,再通过 json.loads() 方法将 JSON 字符串反序列化为字典。

Pickle 序列化

pickle 模块是 Python 特有的序列化模块,它可以将几乎所有的 Python 对象(包括复杂的复合数据结构)进行序列化和反序列化。与 JSON 不同,pickle 序列化后的结果是 Python 特定的二进制格式,不能直接在其他语言中使用。例如:

import pickle
data_dict = {
    'nested_list': [[1, 2], {'sub_key':'sub_value'}]
}
# 序列化
with open('data.pkl', 'wb') as f:
    pickle.dump(data_dict, f)
# 反序列化
with open('data.pkl', 'rb') as f:
    new_dict = pickle.load(f)
print(new_dict)

这里通过 pickle.dump() 将字典 data_dict 序列化并保存到文件 data.pkl 中,再通过 pickle.load() 从文件中读取并反序列化数据。

字典中列表在实际项目中的应用场景

数据分析

在数据分析中,常常需要将不同类别的数据分组存储。例如,有一份销售数据,按照不同地区存储销售记录列表。通过字典中存储列表的结构,可以方便地对每个地区的销售数据进行统计分析,如计算总销售额、平均销售额等。

sales_by_region = {
    'North': [100, 120, 110],
    'South': [90, 85, 95],
    'East': [130, 140, 135]
}
for region, sales in sales_by_region.items():
    total_sales = sum(sales)
    average_sales = total_sales / len(sales)
    print(f"{region} 地区总销售额: {total_sales}, 平均销售额: {average_sales}")

游戏开发

在游戏开发中,例如角色扮演游戏(RPG),可以使用字典存储不同角色的物品列表。每个角色对应一个键,其值是一个包含该角色拥有物品的列表。这样可以方便地管理角色的物品,如添加、删除物品,以及检查角色是否拥有特定物品等。

player_items = {
    'Player1': ['sword', 'shield', 'potion'],
    'Player2': ['bow', 'arrow', 'helmet']
}
# Player1 获得一个新物品
player_items['Player1'].append('key')
print(player_items)

网络爬虫

在网络爬虫项目中,当爬取到不同类型的数据时,可以使用字典中列表的结构进行存储。例如,爬取网页上不同分类的链接列表,每个分类作为字典的键,链接列表作为对应的值。这样便于后续对不同类型链接进行进一步处理,如访问链接、提取信息等。

category_links = {
    'news': ['news1.com', 'news2.com'],
    'products': ['product1.com', 'product2.com']
}
for category, links in category_links.items():
    for link in links:
        # 这里可以添加访问链接并提取信息的代码
        print(f"正在处理 {category} 分类的链接: {link}")

通过以上对 Python 在字典中存储列表的实战技巧的详细介绍,包括基础概念、元素操作、统计分析、排序、复制、序列化以及实际应用场景等方面,相信读者对这一复合数据结构的使用有了更深入的理解和掌握,可以在实际编程项目中灵活运用。