Python之字典

字典

是另一种可变容器模型,且可存储任意类型对象

键一般是唯一的,如果重复,最后的一个键值对会替换前面的,值不需要唯一

d = {key1 : value1, key2 : value2 }

d = {'Z' : '字', 'D' : '典' }

字典创建与删除

1). 简单字典创建

# 代码
ddict = {'name':'kobe','age':'32','id':'24'}
print(ddict['name'])
print(ddict['age'])
print(ddict['id'])

#运行结果
kobe
32
24

2).    内建方法:fromkeys     

字典中的key有相同的value值,默认为None

# 代码
ddict = {}.fromkeys(('name', 'age', 'id'), 'kobe')
print(ddict)
ddict = {}.fromkeys(('name', 'age', 'id'))
print(ddict)

# 运行结果
{'name': 'kobe', 'age': 'kobe', 'id': 'kobe'}
{'name': None, 'age': None, 'id': None}

3).    zip间接创建

# 代码
ddict = zip(['name', 'age', 'id'], ['kobe', '34', '24'])
print(dict(ddict))

# 运行结果
{'name': 'kobe', 'age': '34', 'id': '24'}

字典内建方法

字典应用案例1(词频统计)

作为字典(key-value)的经典应用题目,单词统计几乎出现在每一种语言键值对学习后的必练题目,主要需求: 写一个函数wordcount统计一篇文章的每个单词出现的次数(词频统计)。统计完成后,对该统计按单词频次进行排序

# 代码
content = """
hello python
hello westos
hello world
"""

# 1). 将每个单词拿出来(split) ---> ['hello', 'python', .......]
content_list = content.split()
# 2). 定义一个空字典d={}, 用来存储每个单词出现的次数;
counterDict = {}
# 3). 依次遍历列表的每个单词,
#       d['hello'] = 2
#       d['pyhton'] = 1
for item in content_list:
    # 如果该单词在字典中没有统计过, 赋值为1;
    if item not in counterDict:
        counterDict[item] = 1
    # 如果该单词在字典中已经统计过, 在原有的个数基础上加1;
    else:
        counterDict[item] += 1
print(counterDict)

# 运行结果
{'hello': 3, 'python': 1, 'westos': 1, 'world': 1}

字典应用案例2(列表去重)

通过字典的方式去重,因为字典的key值是不能重复的

# 代码
li = [1, 2, 3, 4, 65, 1, 2, 3]
print({}.fromkeys(li).keys())

# 运行结果
dict_keys([1, 2, 3, 4, 65])

字典应用案例3(switch语句实现)

注意: python中没有switch语句, 如何间接实现?

if实现switch语句

# 代码
grade = input("请输入等级:")
if grade == 'A':
    print("优秀")
elif grade == 'B':
    print("良好")
elif grade == 'C':
    print("及格")
else:
    print("无效的成绩")

# 运行结果
请输入等级:B
良好
请输入等级:F
无效的成绩
通过字典实现switch语句
# 代码
gradeDic = {'A': "优秀", 'B': "良好", 'C': "及格"}
grade = input("请输入等级:")  # A B

# 方法一: 根据key值获取value值: gradeDic[grade]
#       如果key值存在, 返回value值;
#       如果key值不存在, 报错;

if grade in gradeDic:
    print(gradeDic[grade])
else:
    print("无效的成绩")

# 方法二: 根据key值获取value值: dic.get(key)
#       如果key值存在, 返回value值;
#       如果key值不存在,返回None或者你指定的默认值;
print(gradeDic.get(grade, "无效的成绩"))  #默认值是"无效的成绩"

# 运行结果
请输入等级:A
优秀
优秀
请输入等级:S
无效的成绩
无效的成绩

 字典应用案例4(基于用户协同过滤算法的电影推荐代码demo)

题目需求: 假设已有若干用户名字及其喜欢的电影清单,现有某用户,已看过并喜欢一些电影,现在想找个新电影看看,又不知道看什么好。根据已有数据,查找与该用户爱好最相似的用户,也就是看过并喜欢的电影与该用户最接近,然后从那个用户喜欢的电影中选取一个当前用户还没看过的电影,进行推荐。

{ "小明": {"绿皮书", "流浪地球"},  "小红": {"绿皮书", "流浪地球"},  }

技能要点: Python内置函数以及内置字典与集合的用法

推荐资料: http://www.voidcn.com/article/p-yayskzin-zt.html

第一步:产生数据

# 代码
"""
假设已有若干用户名字及其喜欢的电影清单,现有某用户,已看过并喜欢一些电影,现在想找个新电影看看,又不知道看什么好。
根据已有数据,查找与该用户爱好最相似的用户,也就是看过并喜欢的电影与该用户最接近,然后从那个用户喜欢的电影中选取
一个当前用户还没看过的电影,进行推荐。


"""
import random
import pprint

# 1). 设计沪剧存储的数据结构; 字典里面, value值是列表;
movieDb = {}

# 2). 随机生成100个电影名
movies = []
for item in range(100):
    movie_name = '电影' + str(item)
    movies.append(movie_name)
print(movies)

# 3). 随机生成用户和喜欢电影的集合;
for item in range(100):
    name = 'user' + str(item)
    # random.sample([1, 2, 3, 4], 3) ---> 从指定的序列中拿出指定个数据出来;返回的是列表;
    user_movies = random.sample(movies, random.randint(2, 30))
    movieDb[name] = user_movies

# 4). 更加友好的打印数据信息;
# pprint.pprint(movieDb)


# 5). 如何写入文件中;
# json: javascript  object
import json

# 以写的权限打开文件;
f = open('movie.txt', 'w')
# 将python的字典转成json格式的字符串, 并保存到文件对象f中;
# ensure_ascii=False: 中文显示正确
# indent=4缩进进为4个空格;
json.dump(movieDb, f, ensure_ascii=False, indent=4)
# 关闭文件;
f.close()

 数据结果(保存在文件中,由于数据量太大,这里只截取了一部分)

{
    "user0": [
        "电影44",
        "电影12",
        "电影20",
        "电影86",
        "电影43",
        "电影8",
        "电影23",
        "电影69",
        "电影30",
        "电影83",
        "电影36",
        "电影16",
        "电影17",
        "电影3",
        "电影79",
        "电影24",
        "电影91",
        "电影74",
        "电影14",
        "电影9",
        "电影18",
        "电影21",
        "电影70",
        "电影84",
        "电影88"
    ],
    "user1": [
        "电影72",
        "电影28",
        "电影13",
        "电影90",
        "电影88",
        "电影64",
        "电影33",
        "电影91",
        "电影30"
    ],
    "user2": [
        "电影5",
        "电影56",
        "电影81",
        "电影92",
        "电影65",
        "电影71",
        "电影72",
        "电影9",
        "电影66"
    ],
    "user3": [
        "电影47",
        "电影27",
        "电影78",
        "电影25",
        "电影99",
        "电影34",
        "电影94",
        "电影6",
        "电影56",
        "电影81",
        "电影59",
        "电影89",
        "电影86",
        "电影30",
        "电影52",
        "电影93",
        "电影92",
        "电影0",
        "电影66",
        "电影44",
        "电影64",
        "电影13",
        "电影76"
    ]

第二步:推荐电影

# 代码
"""
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。
json模块是实现Python 对象和JSON 字符串之间转换的模块;
"""
import json

"""
pprint 包含一个“美观打印机”,用于生成数据结构的一个美观视图。格式化工具会生成数据结构的一些表示,不仅可以由解释器正确地解析,
而且便于人类阅读。输出尽可能放在一行上,分解为多行时则需要缩进。
"""
import pprint
# Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。
from collections import Counter

# 1). 从文件中读取用户和电影数据
# 打开文件信息, 默认打开方式是读
f = open('movie.txt')
# 将文件中的json字符串转成python便于处理的字典数据类型;
movieDb = json.load(f)
# 关闭文件
f.close()
# print(type(movieDb))
# pprint.pprint(movieDb)


searchUser = input("请输入需要推荐的用户名: ")
# 2).  依次遍历字典的每一个元素, 查找跟user3用户交集最多的用户(user1);
# searchUser 和自己是不需要比较的;
searchUserMovies = set(movieDb.pop(searchUser))
# result存储 searchUser和每个用户喜欢电影交集的个数;= {'user1': 1, 'user2': 2}
result = {}
for user, movies in movieDb.items():
    # 求用户和searchUser交集的个数;
    interaction_count = len(set(movies) & searchUserMovies)
    # 并存储到字典中;
    result[user] = interaction_count

# 3). 打印统计结果
# pprint.pprint(result)


# 4). 对于结果进行排序
# 对字典的value值进行排序, 由大到小;
counter = Counter(result)
# 打印排序结果的前几个, 目前指定的是前5个;
top5UserCounter = counter.most_common(5)
# print(top5UserCounter)


# 5). 获取前5个跟searchUser相似用户喜欢的电影, 并求并集;
# 获取所有跟searchUser最相关的前5个用户名;
top5User = dict(top5UserCounter).keys()
# allUnionMovies 跟searchUser最相关的前5个用户喜欢的电影的并集; 定义空集合用set()
allUnionMovies = set()
for user in top5User:
    # 获取用户喜欢的电影; 列表;
    # 集合添加元素: add: 添加一个元素; update: 一次添加多个元素;
    allUnionMovies.update(movieDb[user])

# 前5个用户喜欢的电影的并集 -  searchUser喜欢的电影
allRecommendMovies = allUnionMovies - searchUserMovies
print(allRecommendMovies)

allRecommendMoviesList = list(allRecommendMovies)  # 集和不能用json,因此转换成了列表
m = open('RecommendMovies.txt', 'w')  # 由于在运行窗口显示不好查看,因此写入一个文件中查看
json.dump(allRecommendMoviesList, m, ensure_ascii=False, indent=4)
f.close()

推荐电影的数据:

[
    "电影45",
    "电影63",
    "电影30",
    "电影60",
    "电影54",
    "电影89",
    "电影57",
    "电影77",
    "电影19",
    "电影3",
    "电影22",
    "电影26",
    "电影68",
    "电影91",
    "电影0",
    "电影92",
    "电影73",
    "电影88",
    "电影53",
    "电影78",
    "电影29",
    "电影13",
    "电影36",
    "电影6",
    "电影62",
    "电影44",
    "电影71",
    "电影95",
    "电影8",
    "电影51",
    "电影1",
    "电影18",
    "电影97",
    "电影11",
    "电影49",
    "电影42",
    "电影2",
    "电影38",
    "电影55",
    "电影46",
    "电影23",
    "电影9",
    "电影98",
    "电影84",
    "电影85",
    "电影81",
    "电影27",
    "电影28",
    "电影69"
]

一键多值字典:defaultdict

collections.defaultdict类,本身提供了默认值的功能, 默认值可以是整形,列表,集合等.  

需求:我们想要一个能将键(key)映射到多个值的字(即所谓的一键多值字典)

解决方案:     1). 字典是一种关联容器,每个键都映射到一个单独的值上。如果想让键映射到多个值,需要将这些多个值保存到容器(列表或者集合)中。

                         2). 利用collections模块中的defaultdict类自动初始化第一个值,这样只需关注添加元素.

# 代码
from collections import  defaultdict
# 创建一个空字典, 所有的value值默认是空列表[]
dict1 = defaultdict(list)
# 判断'a'这个key值是否存在, 如果不存在, 返回[], .append, 在空列表后面追加元素1;
dict1['a'].append(1)
# 判断'a'这个key值是否存在, 如果存在, 获取value值, .append, 在原有的value值后面追加元素1;
dict1['a'].append(2)
dict1['b'].append(4)
print(dict1)

# 创建一个空字典, 所有的value值默认是空集合set()
dict1 = defaultdict(set)
# 判断'a'这个key值是否存在, 如果不存在, 返回set(), .add, 在空列表后面追加元素1;
dict1['a'].add(1)
# 判断'a'这个key值是否存在, 如果存在, 获取value值, .add, 在原有的value值后面追加元素1;
dict1['a'].add(2)

dict1['b'].add(4)
print(dict1)

# 运行结果
defaultdict(<class 'list'>, {'a': [1, 2], 'b': [4]})
defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})

 字典应用案例5(一键多值字典:defaultdict)

用defaultDict来做一个练习,把list(随机生成50个1-100之间的随机数)中大于66的元素和小于66的元素存成

{

'大于66的元素': [71,8 2, ,83], 

'小于66的元素': [1, 2, 3]

}

# 代码
import random
from collections import  defaultdict
import pprint
# 1). 随机生成50个1-100之间的随机数
count = 50
allNums = []
for item in range(count):
    allNums.append(random.randint(1, 100))

# 2). 大于66的元素和小于66的元素
classifyNums = defaultdict(list)
for num in allNums:
    if num > 66:
        classifyNums['大于66的元素'].append(num)
    elif num < 66:
        classifyNums['小于66的元素'].append(num)

pprint.pprint(classifyNums)

# 运行结果
{'大于66的元素': [96, 84, 81, 68, 82, 87, 90, 98, 84, 67, 67, 84, 85],
             '小于66的元素': [31,
                         40,
                         5,
                         43,
                         31,
                         21,
                         61,
                         31,
                         35,
                         33,
                         26,
                         64,
                         45,
                         39,
                         40,
                         4,
                         17,
                         65,
                         39,
                         37,
                         51,
                         50,
                         13,
                         44,
                         50,
                         10,
                         13,
                         57,
                         43,
                         4,
                         9,
                         35,
                         42,
                         35,
                         41,
                         14]})

内置数据结构总结

1)可变数据类型:可以增删改。可变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

     不可变数据类型:不可以增删改。python中的不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象。

2)序列: Python包含列表、元组、字符串、集合, 字典等内建的序列。所有序列类型都可以进行某些特定的操作。可以for循环 有序序列:  这些操作包括:索引(indexing)、切片(sliceing)、连接操作符(adding)、重复操作符(multiplying)以及成员操作符。

     非序列:int, long, float, bool, complex

3)可以for循环: 字符串, 列表, 元组, 集合, 字典

不可以for循环:数值类型(int, long, float, bool, complex)

练习1

问题描述: 有一个列表,其中包括 10 个元素,例如这个列表是[1,2,3,4,5,6,7,8,9,0],要求将列表中的每个元素一次向前移动一个位置,第一个元素到列表的最后,然后输出这个列表。最终样式是[2,3,4,5,6,7,8,9,0,1]

# 代码
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
list0 = list.pop(0)
list.append(list0)
print(list)

# 运行结果
[2, 3, 4, 5, 6, 7, 8, 9, 0, 1]

练习2

问题描述:按照下面的要求实现对列表的操作:   

 1). 产生一个列表,其中有 40 个元素,每个元素是 50 到 100 的一个随机整数     

2). 如果这个列表中的数据代表着某个班级 40 人的分数,请计算成绩低于平均分的学生人数     

3). 对上面的列表元素从大到小排序并输出li.sort(reverse=True)

# 代码
import random

scoreList = []
scoreCount = 0  # 计算总分数
studentCount = 0  # 统计分数低于平均分的学生
for item in range(40):  # 产生40个学生的成绩
    score = random.randint(50, 100)
    scoreList.append(score)
    scoreCount += score
print(scoreList)
length = len(scoreList)  # 学生人数
average = scoreCount / length  # 平均分
print(average)
for item in scoreList:
    if item < average:
        studentCount += 1
print(studentCount)
scoreList.sort(reverse=True)  # 从大到小排序
print(scoreList)

# 运行结果
[98, 100, 58, 55, 78, 80, 66, 63, 89, 95, 89, 71, 68, 64, 82, 86, 98, 91, 72, 66, 93, 56, 72, 77, 84, 87, 94, 79, 50, 65, 90, 64, 60, 92, 65, 73, 56, 89, 91, 92]
77.45
19
[100, 98, 98, 95, 94, 93, 92, 92, 91, 91, 90, 89, 89, 89, 87, 86, 84, 82, 80, 79, 78, 77, 73, 72, 72, 71, 68, 66, 66, 65, 65, 64, 64, 63, 60, 58, 56, 56, 55, 50]

练习3

问题描述: 如果将一句话作为一个字符串,那么这个字符串中必然会有空格(这里仅讨论英文),比如"How are you.",但有的时候,会在两个单词之间多大一个空格。现在的任务是,如果一个字符串中有连续的两个空格,请把它删除。

# 代码
str1 = "how   are  you   "
print(str1.split())
print(' '.join(str1.split()))

# 运行结果
['how', 'are', 'you']
how are you

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值