2025-09-10:仓库迁移
This commit is contained in:
14
1.数据结构与算法/1.序列分解.py
Normal file
14
1.数据结构与算法/1.序列分解.py
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
# 普通的序列分解方式
|
||||
def normal_func(list):
|
||||
# list是可迭代对象,能够直接分解成多个元素
|
||||
length = list.__len__()
|
||||
length= 2
|
||||
x, y = list
|
||||
|
||||
# 如果list长度和接数据的元素数量不匹配,会造成错误
|
||||
x, y, z = list
|
||||
|
||||
# 在知道元素顺序的情况下想要丢弃list中的某些元素,可以用下划线来无视变量
|
||||
_ ,y = list
|
||||
|
25
1.数据结构与算法/10.移除重复元素保留顺序.py
Normal file
25
1.数据结构与算法/10.移除重复元素保留顺序.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# 如果序列中存储的元素是可哈希的,那就可以使用集合与生成器解决
|
||||
|
||||
def dequpe(items):
|
||||
seen = set()
|
||||
for item in items:
|
||||
if item not in seen:
|
||||
yield item
|
||||
seen.add(item)
|
||||
|
||||
# 如果序列里的元素是不可哈希的,比如字典这种东西,就要先转化为可哈希对象;
|
||||
# 这里自定义的key函数就起到了给字典解包的作用
|
||||
|
||||
def dequpe(items, key):
|
||||
seen = set()
|
||||
for item in items:
|
||||
val = item if key is None else key(item)
|
||||
if val not in seen:
|
||||
yield item
|
||||
seen.add(val)
|
||||
|
||||
# 如果单纯的做不改变顺序的去重,直接转集合再转列表就行了
|
||||
|
||||
a = [1,5,2,1,9,1,5,10]
|
||||
a = list(set(a))
|
||||
print(a)
|
18
1.数据结构与算法/11.切片命名.py
Normal file
18
1.数据结构与算法/11.切片命名.py
Normal file
@@ -0,0 +1,18 @@
|
||||
items = [0,1,2,3,4,5,6]
|
||||
|
||||
# 我们可以使用内置的slice函数对切片进行命名,参数分别为start|stop|step
|
||||
a = slice(2,6,2)
|
||||
|
||||
print(items[a])
|
||||
print(a.start, a.stop, a.step)
|
||||
|
||||
# indeces方法可以帮我们把start和stop自动限制在序列长度内,并返回一个限制后的切片
|
||||
s = "sukahelloworld"
|
||||
# 上面那个可能看着不明显,但是下面这个看着就明显多了
|
||||
# s = "suka"
|
||||
|
||||
print(a.indices(len(s)))
|
||||
|
||||
# 因为返回的是元组,所以要使用得先解包
|
||||
for i in range(*a.indices(len(s))):
|
||||
print(s[i])
|
24
1.数据结构与算法/12.找出现最多元素.py
Normal file
24
1.数据结构与算法/12.找出现最多元素.py
Normal file
@@ -0,0 +1,24 @@
|
||||
words = ["look", "into", "my", "eyes", "look", "into", "my", "eyes",
|
||||
"the", "eyes", "the", "eyes", "the", "eyes", "not", "around", "the",
|
||||
"eyes", "don't", "look", "around", "the", "eyes", "look", "into",
|
||||
"my", "eyes", "you're", "under"]
|
||||
|
||||
# collect里面的Counter库可以帮我们计数
|
||||
from collections import Counter
|
||||
|
||||
word_counts = Counter(words)
|
||||
top_three = word_counts.most_common(3)
|
||||
print(top_three)
|
||||
|
||||
# Counter的底层是一个字典,是一个DefaultDict,这里处于学习目的把它实现一遍
|
||||
from collections import defaultdict
|
||||
|
||||
def counter(word_list):
|
||||
counter = defaultdict(int)
|
||||
for word in word_list:
|
||||
counter[word] += 1
|
||||
|
||||
return counter
|
||||
|
||||
print(counter(words))
|
||||
|
25
1.数据结构与算法/13.字典公共键排序.py
Normal file
25
1.数据结构与算法/13.字典公共键排序.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# 我们有一个字典列表,想要按照字典里的某些键对列表进行排序
|
||||
# 字典列表如下:
|
||||
rows = [
|
||||
{"fname":"Brian", "lname": "Jones", "uid":1003},
|
||||
{"fname":"David", "lname": "Beazley", "uid":1002},
|
||||
{"fname":"John", "lname": "Cleese", "uid":1001},
|
||||
{"fname":"Big", "lname": "Jones", "uid":1004}
|
||||
]
|
||||
|
||||
# 这时候用到itemgetter模块
|
||||
from operator import itemgetter
|
||||
|
||||
# itemgetter的主要功能是通过可查询的标记进行数据获取;
|
||||
# 下面分别根据fname和uid进行数据获取
|
||||
|
||||
rows_by_fname = sorted(rows, key=itemgetter("fname"))
|
||||
rows_by_uid = sorted(rows, key=itemgetter("uid"))
|
||||
|
||||
print(rows_by_fname)
|
||||
print(rows_by_uid)
|
||||
|
||||
# 当然,itemgetter也能被lambda函数替代,替代操作如下:
|
||||
|
||||
rows_by_fname_v2 = sorted(rows, key= lambda row: row["fname"])
|
||||
print(rows_by_fname_v2)
|
32
1.数据结构与算法/14.原生不支持比较操作的对象排序.py
Normal file
32
1.数据结构与算法/14.原生不支持比较操作的对象排序.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# 众所周知,对class这种原生不支持比较的对象直接进行比较会造成暴毙;
|
||||
# 我们但如果非比不可呢?比如这个东西:
|
||||
class User:
|
||||
def __init__(self,user_id):
|
||||
self.user_id = user_id
|
||||
|
||||
def __repr__(self):
|
||||
return "User({})".format(self.user_id)
|
||||
|
||||
# 这里有一个列表user
|
||||
user = [User(23), User(3), User(99)]
|
||||
|
||||
# 如果这时候需要按照某个属性给这个列表排序,那么直接sorted会报错:
|
||||
try:
|
||||
sorted(user)
|
||||
pass
|
||||
except:
|
||||
print("你看吧,报错了")
|
||||
|
||||
# 这里的原因是对象不能直接进行比较,所以想要排序只能按照对象里的某个属性
|
||||
# 有两种解决方案:
|
||||
sorted_list = sorted(user, key=lambda x: x.user_id)
|
||||
print(sorted_list)
|
||||
|
||||
# 要么就用operator库里的attrgetter
|
||||
from operator import attrgetter
|
||||
sorted_list = sorted(user, key=attrgetter("user_id"))
|
||||
print(sorted_list)
|
||||
|
||||
# 用这东西的好处和针对字典的itemgetter一样,可以取多个字段
|
||||
# sorted_list = sorted(user, key=attrgetter("user_id", "word_2", "word_3", ...))
|
||||
# 同样的,max和min这种有key参数的内建函数都能用这些东西折腾
|
39
1.数据结构与算法/15.根据字段分组.py
Normal file
39
1.数据结构与算法/15.根据字段分组.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# 假如我们有一个记录需要进行分组
|
||||
|
||||
rows = [
|
||||
{"address": "5412 N CLARK", "date": "07/01/2012"},
|
||||
{"address": "5148 N CLARK", "date": "07/04/2012"},
|
||||
{"address": "5800 E 58TH", "date": "07/02/2012"},
|
||||
{"address": "2122 N CLARK", "date": "07/03/2012"},
|
||||
{"address": "5645 N RAVENSWOOD", "date": "07/02/2012"},
|
||||
{"address": "1060 W ADDISON", "date": "07/02/2012"},
|
||||
{"address": "4801 N BROADWAY", "date": "07/01/2012"},
|
||||
{"address": "1039 W GRANVILLE", "date": "07/04/2012"},
|
||||
]
|
||||
|
||||
# 如果我们想按日期进行分组,那itertools里的groupby会很好用
|
||||
from operator import itemgetter
|
||||
from itertools import groupby
|
||||
|
||||
# 因为groupby只能检查连续的项,所以我们先对列表进行排序
|
||||
rows.sort(key=itemgetter("date"))
|
||||
print(rows)
|
||||
|
||||
# 然后我们进行分组操作:
|
||||
for date, items in groupby(rows, itemgetter("date")):
|
||||
print(date)
|
||||
for i in items:
|
||||
print(' ', i)
|
||||
# groupby每次返回的是一个值(分组名称)和一个子迭代器(组内数据)
|
||||
|
||||
|
||||
# 当然如果是单纯的分组,一键多值字典是个好东西
|
||||
from collections import defaultdict
|
||||
data = defaultdict(list)
|
||||
for item in rows:
|
||||
data[item["date"]].append(item)
|
||||
|
||||
print(data)
|
||||
|
||||
# 在不考虑内存开销的情况下,这东西比先排序再groupby快
|
||||
|
71
1.数据结构与算法/16.元素筛选.py
Normal file
71
1.数据结构与算法/16.元素筛选.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# 比如我有一个列表
|
||||
mylist = [1,4,-5,10,-7,2,3,-1]
|
||||
|
||||
# 最脑瘫的方法就是用列表推导式重新生成一遍
|
||||
filted_list_b0 = [x for x in mylist if x > 0]
|
||||
filted_list_s0 = [x for x in mylist if x < 0]
|
||||
# print(filted_list_b0)
|
||||
|
||||
|
||||
|
||||
# 当然如果列表很大,这样做会裂开,因为列表推导式本质上是遍历,会建立一份mylist的复制
|
||||
# 这个时候我们可以用生成器的方式表达解析结果以节省内存
|
||||
filted_list_b0 = (x for x in mylist if x > 0)
|
||||
# for i in filted_list_b0:
|
||||
# print(i)
|
||||
|
||||
|
||||
|
||||
# 当然有的列表比较抽象:
|
||||
mylist_suka = ['1', '2', '-3', '-', '4', 'N\A', '5']
|
||||
|
||||
# 这个时候我们可以先写逻辑进行过滤:
|
||||
def drop_suka(val):
|
||||
try:
|
||||
x = int(val)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
# 然后我们用内建的filter函数进行过滤,
|
||||
# 第一个位置是一个值判断布尔函数,第二个参数是要过滤的列表,布尔函数里写过滤逻辑;
|
||||
# filter返回一个迭代器,所以可以直接用list方法转成列表
|
||||
my_nonsuka_list = list(filter(drop_suka, mylist_suka))
|
||||
# print(my_nonsuka_list)
|
||||
|
||||
|
||||
|
||||
# 列表推导式和生成器推导式都可以在值的位置进行:
|
||||
# 1.计算 x*2
|
||||
# 2.三元判断 x*2 if x < 1 else x
|
||||
filted_list_b0 = [x*2 if x < 1 else x for x in mylist if x > 0]
|
||||
filted_list_b0 = (x*2 if x < 1 else x for x in mylist if x > 0)
|
||||
|
||||
|
||||
|
||||
# 如果要筛选的元素在另一个列表里怎么办?比如我们有:
|
||||
rows = [
|
||||
"5412 N CLARK",
|
||||
"5148 N CLARK",
|
||||
"5800 E 58TH",
|
||||
"2122 N CLARK",
|
||||
"5645 N RAVENSWOOD",
|
||||
"1060 W ADDISON",
|
||||
"4801 N BROADWAY",
|
||||
"1039 W GRANVILLE",
|
||||
]
|
||||
|
||||
counts = [0,3,10,4,1,7,6,1]
|
||||
|
||||
# counts表示rows里面对应元素出现的次数,如果我们想找count>5的元素咋整?
|
||||
# 1.搞一个布尔列表,告诉程序谁才是我们要的
|
||||
wanted = [n > 5 for n in counts] # 这和[n for n in counts if n > 5]不一样,之前是在for的同时筛选,现在是for完看看是否符合n>5
|
||||
# print(wanted)
|
||||
# 2.用itertools的compress函数来进行对比
|
||||
from itertools import compress
|
||||
|
||||
# itertools里的compress函数输入一个列表和一个布尔列表,返回一个迭代器,里面是列表中同样位置在布尔列表里为True的元素
|
||||
result = list(compress(rows, wanted))
|
||||
print(result)
|
||||
|
19
1.数据结构与算法/17.字典子集.py
Normal file
19
1.数据结构与算法/17.字典子集.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# 假如我们有一个字典,需要提取子集:
|
||||
price = {
|
||||
"ACME": 45.23,
|
||||
"AAPL": 612.78,
|
||||
"IBM": 205.55,
|
||||
"HPQ": 37.2,
|
||||
"FB": 10.75
|
||||
}
|
||||
|
||||
# 直接用字典推导式
|
||||
p1 = {key :value for key, value in price.items() if value > 200}
|
||||
|
||||
# 提取key也是
|
||||
keys = {"AAPL", "IBM", "HPQ", "MSFT"}
|
||||
p2 = {key : value for key, value in price.items() if key in keys}
|
||||
|
||||
# 字典推导式是最快的方法,比下面两个办法都快:
|
||||
dict((key, value) for key, value in price if value > 100) # 快两倍
|
||||
{key:price[key] for key in price.keys() if key in price.keys() & keys} # 快1.6倍
|
37
1.数据结构与算法/18.将名称映射到序列元素.py
Normal file
37
1.数据结构与算法/18.将名称映射到序列元素.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# collection库中有一个东西叫做namedtuple,有点像结构体,可以给元组中的元素起名
|
||||
from collections import namedtuple
|
||||
|
||||
Subscribe = namedtuple('Subscriber', ["addr", "joined"])
|
||||
sub = Subscribe("suka@qq.com", "2024/07/17")
|
||||
print(sub)
|
||||
print(sub.addr)
|
||||
print(sub.joined)
|
||||
|
||||
# 可以看到,这个东西和对象有点相似,但这种操作又保留了适用于元组的所有操作,比如索引和分解
|
||||
print(sub[0])
|
||||
print(len(sub))
|
||||
addr, joined = sub
|
||||
print(addr, joined)
|
||||
|
||||
# 如果我们获取的数据总是list类型,不是标准的json数据,那这东西就很有用
|
||||
# 比如返回的数据是这种东西: data = [0,1,1,3,2,6]
|
||||
# 如果是这种非标数据,普通代码处理长这样:
|
||||
def compute_cost(records):
|
||||
total = 0.0
|
||||
for rec in records:
|
||||
total += rec[1] * rec[2]
|
||||
|
||||
return total
|
||||
|
||||
# 这造成一个问题,鬼知道rec[1]和rec[2]是什么东西,代码可读性很傻逼;
|
||||
# 所以我们可以在拿到数据的时候先标准化一下
|
||||
Stock = namedtuple("Stock", ['name', 'share', 'price'])
|
||||
def compute_cost(records):
|
||||
total = 0.0
|
||||
for rec in records:
|
||||
stock = Stock(*rec)
|
||||
total += stock.share * stock.price
|
||||
|
||||
return total
|
||||
|
||||
# 当然如果返回的已经是对象了,那就没有做namedtuple的必要了,在不想用类的时候可以用这东西替代字典
|
30
1.数据结构与算法/19.同时对数据做转化和换算.py
Normal file
30
1.数据结构与算法/19.同时对数据做转化和换算.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# 这是一种简化操作,可以将转换和换算合为一体,比如我们有一个列表
|
||||
nums = [1,2,3,4,5]
|
||||
|
||||
# 计算平方和我们一般这样子做:
|
||||
nums_square = [x*x for x in nums]
|
||||
s = sum(nums_square)
|
||||
|
||||
# 这个时候我们就可以这样来简化一下运算:
|
||||
s = sum(x*x for x in nums)
|
||||
|
||||
|
||||
# 又或者我们要在一堆参数中间加一些分隔符:
|
||||
# 注意,这里的join和os.path.join不一样,这里是用来给jion输入的列表加分隔符的
|
||||
s = ("ACME", 50, 123.45)
|
||||
print(','.join(str(x) for x in s))
|
||||
|
||||
# 这里我们将生成器表达式从()里薅出来,当作可迭代参数塞进了函数里,这样避免了列表生成器造成的内存浪费
|
||||
|
||||
# 对单个字典内,我们用键值反转的方法来找元素,但是如果这是一个字典列表,那情况就大大不同了
|
||||
portfolio = [
|
||||
{'name': 'GOOG', 'shares': 50},
|
||||
{'name': 'YHOO', 'shares': 75},
|
||||
{'name': 'AOL', 'shares': 20},
|
||||
{'name': 'SCOX', 'shares': 65}
|
||||
]
|
||||
max_share = max(portfolio, key=lambda x: x["shares"])
|
||||
print(max_share)
|
||||
# 当然如果仅仅只要拿到最小值就用到了生成器表达式内嵌的方法
|
||||
max_share_num = max(s['shares'] for s in portfolio)
|
||||
print(max_share_num)
|
36
1.数据结构与算法/2.从任意可迭代对象中分解元素.py
Normal file
36
1.数据结构与算法/2.从任意可迭代对象中分解元素.py
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
# 可迭代对象分解
|
||||
def iterable_breakdown(list):
|
||||
# 如果可迭代对象长度大于接数据的变量数量,分解值过多报错
|
||||
length = list.__len__()
|
||||
length = 20
|
||||
# 这样会报错,因为list长度是20,但分解变量只有两个
|
||||
x, y = list
|
||||
|
||||
# 想要接住任意长度的列表,需要用*
|
||||
# *x是包含list前n-1个元素的列表,y是最后一个元素
|
||||
# 我们可以在任意位置接入带*的参数来接住一些值,这些值会在*变量中以列表存储
|
||||
*x, y = list
|
||||
x, *y, z = list
|
||||
|
||||
# 假设有一个变长元组序列
|
||||
record = [("foo",1,2),("bar","suka"),("foo",2,4)]
|
||||
|
||||
def do_foo(x,y):
|
||||
print(x,y)
|
||||
|
||||
def do_bar(s):
|
||||
print(s)
|
||||
|
||||
# 我们可以使用*来解包从而将参数薅出来
|
||||
for tag, *args in record:
|
||||
if tag == "foo":
|
||||
do_foo(*args)
|
||||
elif tag == "bar":
|
||||
do_bar(*args)
|
||||
|
||||
# 同理,也可以用*变量来占位挖掉不要的变量,比如在特定位置用*ignore或*_来挖掉参数
|
||||
|
||||
|
||||
|
||||
|
57
1.数据结构与算法/20.多个映射转换成单个映射.py
Normal file
57
1.数据结构与算法/20.多个映射转换成单个映射.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 假如又两个字典:
|
||||
a = {"x":1, "z":3}
|
||||
b = {"y":2, "z":4}
|
||||
|
||||
# 怎么将这两个字典映射到一个新字典里呢?愚蠢的办法是使用字典合并
|
||||
|
||||
# 这个方法会把右边的b刷写到a里
|
||||
c = a|b
|
||||
print(c)
|
||||
# 但是,你会发现,如果原字典被改了,那c不会有变化:
|
||||
a["x"] = 2
|
||||
print(c)
|
||||
|
||||
# 这个时候使用映射方案的chainmap就会很好用
|
||||
from collections import ChainMap
|
||||
c = ChainMap(a,b)
|
||||
|
||||
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
|
||||
print(len(c))
|
||||
|
||||
# 如果此时更改原字典的值:
|
||||
a["x"] = 1
|
||||
|
||||
# 输出也跟着更改了
|
||||
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
|
||||
print(len(c))
|
||||
|
||||
# 注,chainmap中如果有重复的键,则会采用左值,比如上面的例子使用a["z"]作为重复键z的取值;
|
||||
# 如果修改字典值,也会作用在左值上
|
||||
del c["z"]
|
||||
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
|
||||
print(a, b)
|
||||
# 如果尝试删除a里已经没有但b里有的键,那么会报错
|
||||
try:
|
||||
del c["z"]
|
||||
except:
|
||||
print("在a里没找到键")
|
||||
|
||||
# 这东西的底层其实是一个链表,演示如下:
|
||||
dic = ChainMap()
|
||||
dic["x"] = 1
|
||||
dic = dic.new_child()
|
||||
print(dic)
|
||||
dic["x"] = 2
|
||||
dic = dic.new_child()
|
||||
print(dic)
|
||||
dic["x"] = 3
|
||||
print(dic)
|
||||
# 从这里我们开始回溯历史
|
||||
dic = dic.parents
|
||||
print(dic)
|
||||
dic = dic.parents
|
||||
print(dic)
|
||||
dic = dic.parents
|
||||
print(dic)
|
||||
|
||||
# 可以看到我们用new_child()函数创建了一个新节点;用parents属性来回溯
|
19
1.数据结构与算法/3.保存最后N个元素.py
Normal file
19
1.数据结构与算法/3.保存最后N个元素.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# 队列可以对最后N个元素进行保存
|
||||
from collections import deque
|
||||
|
||||
# 从历史记录列表history得到length条最新历史记录
|
||||
def latest_history(history, length):
|
||||
window = deque(maxlen=length)
|
||||
for record in history:
|
||||
window.append(record)
|
||||
|
||||
# window引用双头队列组件deque,该组件有方法如下
|
||||
# 从队尾加入
|
||||
window.append(1)
|
||||
# 从队尾弹出
|
||||
window.pop()
|
||||
# 从队头加入
|
||||
window.appendleft(1)
|
||||
# 从队头弹出
|
||||
window.popleft()
|
||||
|
33
1.数据结构与算法/4.最大N个和最小N个.py
Normal file
33
1.数据结构与算法/4.最大N个和最小N个.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import heapq
|
||||
|
||||
# heapq里有两个函数,nlargest和nsmallest可以找最大N个和最小N个;
|
||||
# 参数接受一个列表和一个N
|
||||
|
||||
def max_n(search_list, n):
|
||||
list_max_n = heapq.nlargest(n ,search_list)
|
||||
return list_max_n
|
||||
|
||||
def min_n(search_list, n):
|
||||
list_min_n = heapq.nsmallest(n, search_list)
|
||||
return list_min_n
|
||||
|
||||
# 这两个函数都提供了一个key输入来实现在字典列表中的应用
|
||||
def max_in_dictlist(search_list, n, key):
|
||||
max_key_n = heapq.nlargest(n, search_list, key=lambda dic : dic[key])
|
||||
return max_key_n
|
||||
|
||||
# 如果寻找最大N个和最小N个元素,这个方法在N的规模不大的时候好用;
|
||||
# 当日在N=1的时候还是用max和min方法更快,要是N巨大那就得排序了
|
||||
|
||||
# heapq事实上是一个堆方法,将列表在底层序列化为一个最小堆
|
||||
def heapq_func():
|
||||
ori_list = [1,2,3,4,5]
|
||||
heap = list(ori_list)
|
||||
# 将列表进行堆排序
|
||||
heapq.heapify(heap)
|
||||
# 弹出堆顶元素
|
||||
heapq.heappop(heap)
|
||||
|
||||
if __name__ == '__main__':
|
||||
l = [1,2,3,4,5]
|
||||
print(max_n(l, 3))
|
43
1.数据结构与算法/5.优先级队列.py
Normal file
43
1.数据结构与算法/5.优先级队列.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import heapq
|
||||
|
||||
|
||||
# 优先级队列(使用小根堆实现)
|
||||
class PriorityQueue:
|
||||
def __init__(self):
|
||||
self._queue = []
|
||||
# 由于优先级在比较大小时可能相同造成比较失败,维护一个下标index来进行二级辨识
|
||||
self._index = 0
|
||||
|
||||
# 由于heapq的原理是生成一个小根堆,所以优先级取负,这样优先级越大,堆识别到的优先级越小;引入index,在优先级相同时比较入栈先后顺序
|
||||
def push(self, item, priority):
|
||||
heapq.heappush(self._queue, (-priority, self._index, item))
|
||||
self._index += 1
|
||||
|
||||
# 弹出堆顶值
|
||||
def pop(self):
|
||||
return heapq.heappop(self._queue)[-1]
|
||||
|
||||
|
||||
# 在Python中,实例化对象是不可以直接进行比较的,例如:
|
||||
class Item:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
return 'Item {!r}'.format(self.name)
|
||||
# a = Iter('foo') b = Iter('bar'), 进行a<b比较会输出报错
|
||||
|
||||
# 一个优先级队列的简单调用示例
|
||||
if __name__ == "__main__":
|
||||
q = PriorityQueue()
|
||||
q.push(Item("foo"), 1)
|
||||
q.push(Item("bar"), 5)
|
||||
q.push(Item("spam"), 4)
|
||||
q.push(Item("grok"), 1)
|
||||
a = q.pop()
|
||||
b = q.pop()
|
||||
c = q.pop()
|
||||
d = q.pop()
|
||||
print(a)
|
||||
|
38
1.数据结构与算法/6.一键多值字典.py
Normal file
38
1.数据结构与算法/6.一键多值字典.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
# 当你新建一个普通字典,对字典中不存在的key进行调用时会报错
|
||||
a = {}
|
||||
try:
|
||||
print(a["key"])
|
||||
pass
|
||||
except:
|
||||
print("err")
|
||||
|
||||
|
||||
# 如果使用defaultdict进行字典初始化建立,就不存在这个问题;
|
||||
# 当出现不存在的key的时候,会根据默认设置进行默认值创建
|
||||
b = defaultdict(list)
|
||||
print(b["key"])
|
||||
|
||||
# 但是这样就有一个问题,这个key就会一直在这里等待调用,如果没有用到就是垃圾
|
||||
print(b)
|
||||
|
||||
# 这个方法可以用于记录的添加;比如一个方法如下:
|
||||
|
||||
pairs = [{"a":10},{"b":10},{"b":10}]
|
||||
d = {}
|
||||
for key, value in pairs:
|
||||
if key not in d:
|
||||
d[key] = []
|
||||
d[key].append(value)
|
||||
|
||||
# 很明显这样就显得很蠢,我还要判断一下键在不在里面
|
||||
# 使用defaultdict就没有这个困扰,直接省略一键添加
|
||||
|
||||
d = defaultdict(list)
|
||||
for key, value in pairs:
|
||||
d["key"].append(value)
|
||||
|
||||
# 当然为了避免生成空键,使用这东西的时候切记在里面翻东西的时候别直接用dict[key]输入;
|
||||
# 先用keys函数拿到所有键再动手
|
20
1.数据结构与算法/7.有序字典.py
Normal file
20
1.数据结构与算法/7.有序字典.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from collections import OrderedDict
|
||||
|
||||
# 如果需要严格控制字典元素的顺序,可以使用OrderedDict
|
||||
# 比如用于网络通信协议的未序列化字典对象
|
||||
|
||||
d = OrderedDict()
|
||||
d['foo'] = 1
|
||||
d['bar'] = 2
|
||||
d['spam'] = 3
|
||||
d['grok'] = 4
|
||||
|
||||
for key in d:
|
||||
print(d[key])
|
||||
|
||||
# 这样就可以序列化得到一个有序的json编码
|
||||
import json
|
||||
a = json.dumps(d)
|
||||
print(a)
|
||||
|
||||
# 尤其注意:这东西内部有一个双向链表导致它的内存开支有点恐怖,大规模情况下谨慎使用
|
28
1.数据结构与算法/8.字典计算问题.py
Normal file
28
1.数据结构与算法/8.字典计算问题.py
Normal file
@@ -0,0 +1,28 @@
|
||||
price = {
|
||||
"ACME": 45.23,
|
||||
"AAPL": 612.78,
|
||||
"IBM": 205.55,
|
||||
"HPQ": 37.2,
|
||||
"FB": 10.75
|
||||
}
|
||||
|
||||
# 对这样的数据,有时候我们想找到最大值对应的键
|
||||
# 传统方法长这样
|
||||
a = max(price.values())
|
||||
print(a)
|
||||
for key, value in price.items():
|
||||
if value == a:
|
||||
print(key)
|
||||
# 显然,我们要对字典里的这些东西进行遍历才能根据值把键找出来
|
||||
|
||||
# 如果我们不想要这样的开销,可以把键值反转:
|
||||
|
||||
max_price = max(zip(price.values(), price.keys()))
|
||||
print(max_price)
|
||||
|
||||
# 注意,在对键值反转的zip中使用max和min这类函数时需要注意,如果出现:
|
||||
# a = {10, "AA"}, b = {10, "ZZ"}的情况
|
||||
# 由于值相同,会根据键大小返回结果
|
||||
# 所以如果有多个值相同的字段,还得是老办法
|
||||
max_price = [key for value, key in zip(price.values(), price.keys()) if value == a]
|
||||
print(max_price)
|
33
1.数据结构与算法/9.字典差异.py
Normal file
33
1.数据结构与算法/9.字典差异.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# 我们有两个字典如下:
|
||||
|
||||
a = {
|
||||
"x":1,
|
||||
"y":2,
|
||||
"z":3
|
||||
}
|
||||
|
||||
b = {
|
||||
"w":10,
|
||||
"x":11,
|
||||
"y":12
|
||||
}
|
||||
|
||||
# 如果想要得到相同处,只需要用keys和items这类可迭代方法执行集合操作就行
|
||||
|
||||
# 大家都有
|
||||
print(a.keys() & b.keys())
|
||||
|
||||
# a有b没有
|
||||
print(a.keys() - b.keys())
|
||||
|
||||
# b有a没有
|
||||
print(b.keys() - a.keys())
|
||||
|
||||
# 想快速给a减键,可以这样:
|
||||
c = {key:a[key] for key in a.keys() - {"w", "z"}}
|
||||
print(c)
|
||||
|
||||
# python3.9更新了使用|的字典合并和与+=一样的合并运算符|=
|
||||
d = a
|
||||
d |= b
|
||||
print(d)
|
Reference in New Issue
Block a user