leetcode 和剑指 中python的常用数据结构和简化代码小技巧汇总【持续更新】

列表list

列表的切片
A[n: m: x] ---- n:m索引,x步长
用另一个列表对原列表中的所有元素赋值(非引用,不改变原列表的地址)

matrix = matrixRotate  # 引用赋值
matrix[:] = matrixRotate	# 非引用赋值

取二维列表的最大值。不能像numpy一样直接np.max(array),也不能max(max(array)), 因为对于二维list数据,max(array)出来的是首元素最大的一维列表,再max出来的是该一维列表的最大值,这并非是全局最值。因此可先求每行的最值,再从当中求最值。

在这里插入图片描述

max(map(max, array))
max([max(row) for row in array])

列表的拷贝

一维列表的拷贝:此时为深拷贝,dp和nums指向两片不同的地址,修改dp,nums不受影响

dp = nums[:] 

二维列表的拷贝:此时为浅拷贝,dp和triangle指向相同的地址,修改dp,triangle也受影响

dp = triangle[:]

若要深拷贝二维列表,则应该

dp = [[x for x in y] for y in triangle]

二维列表展成一维

from itertools import chain
list(chain.from_iterable(array))	## 自动解压可迭代对象
list(chain(*array))	## 手动解压可迭代对象
[array[i][j] for i in range(len(array)) for j in range(len(array[0]))]
[array[i][j] for i, j in itertools.product(range(len(array)), range(len(array[0])))]
[aaa for aa in a for aaa in aa]


eg:
from_iterable = chain.from_iterable(['geeks', 
                                     'for',
                                     'geeks',
                                     ['w', 'i', 'n', 's']])
print(list(from_iterable))
[‘g’, ‘e’, ‘e’, ‘k’, ‘s’, ‘f’, ‘o’, ‘r’, ‘g’, ‘e’, ‘e’, ‘k’, ‘s’, ‘w’, ‘i’, ‘n’, ‘s’]

字符串

字符串匹配接口

str.find(str, beg=0, end=len(string))
str -- 指定检索的字符串
beg -- 开始索引,默认为0。
end -- 结束索引,默认为字符串的长度。
如果包含子字符串返回首个成功匹配的索引值,否则返回-1, 若要匹配的子串为空串,则返回0

str.index(str, beg=0, end=len(string))
区别在于:如果包含子字符串返回开始的索引值,否则抛出异常。

集合

往集合中添加元素。使用 add() 方法添加的元素,只能是数字、字符串、元组或者布尔类型(True 和 False)值,不能添加列表、字典、集合这类可变的数据,否则 Python 解释器会报 TypeError 错误。

a = set()
a.add(ele)	##注意只能添加一个元素,不能传入列表等可迭代参数
a.update(list)	## update可传入列表
a.union(b)	## 集合a和b取并集
a.remove(ele)	## ele不在集合中就会报错
a.discard(ele)	## ele不在集合中不会报错

在这里插入图片描述

字典dict

  1. collections.defaultdict类的介绍:

defaultdict是Python内建dict类的一个子类,第一个参数为default_factory属性提供初始值,默认为None。它覆盖一个方法并添加一个可写实例变量。它的其他功能与dict相同,但会为一个不存在的键提供默认值,从而避免KeyError异常。

一般的dict类型会导致KeyError异常:

bag = ['apple', 'orange', 'cherry', 'apple','apple', 'cherry', 'blueberry']
count = {}
for fruit in bag:
    count[fruit] += 1
    
错误:
KeyError: 'apple'

若想要初始化字典元素为0,可以使用defaultdict

import collections
bag = ['apple', 'orange', 'cherry', 'apple','apple', 'cherry', 'blueberry']
count = collections.defaultdict(int)
for fruit in bag:
    count[fruit] += 1

输出:
defaultdict(<class 'int'>, {'apple': 3, 'orange': 1, 'cherry': 2, 'blueberry': 1})

同样,也可以初始化字典元素为listdefaultdict(list),这样后面可以直接append而不需要初始化空列表。

  1. dict常用方法
dict.update(dict2)	# 把字典dict2更新到dict里
eg:
a = {'one': 1, 'two': 2, 'three': 3}
a.update({'one':4.5, 'four': 9.3})
>>{'one': 4.5, 'two': 2, 'three': 3, 'four': 9.3}

dict.get(key, default=None)	#返回指定键的值,如果键不在字典中返回默认值 None 或者设置的默认值。
eg:
visitdict = {'a':1, 'b':1}
visitdict.get('a', default=0)
>>1
visitdict.get('c', default=0)
>>0

#删除字典
dict.pop(key, default)	#弹出(删除并返回)指定键的值,如果键不在字典中返回默认值 None 或者设置的默认值。
eg:
dic= dict(a='a', b='b', c='c')
k = dic.pop(a) 
>>'a'
k = dic.pop(b, 'sss') 
>>'b'
k = dic.pop(d)
>>Error
k = dic.pop(n, 'sss')
>>'sss'
del dic[c]	##删除键值对



#创建字典
dict() 
eg:
>>>dict()                        # 创建空字典
{}

# 注意:通过传入关键字创建字典时,会将关键字看待为字符,即使关键字为某一变量
dict(a='a', b='b', t='t')     # 传入关键字	dict(**kwarg),即使a为某一变量,也会变为'a'
>>> {'a': 'a', 'b': 'b', 't': 't'}

dict(zip(['one', 'two', 'three'], [1, 2, 3]))   # 映射函数方式来构造字典	dict(mapping, **kwarg)
>>> {'three': 3, 'two': 2, 'one': 1} 
dict([('one', 1), ('two', 2), ('three', 3)])    # 可迭代对象方式来构造字典 dict(iterable, **kwarg)
>>> {'three': 3, 'two': 2, 'one': 1}

注意:通过传入关键字创建字典时,会将关键字看待为字符,即使关键字为某一变量
在这里插入图片描述

队列

- 实现方式一: Queue的基本FIFO队列
  • 添加元素:q.put(data)
  • 弹出元素:q.get()
import Queue

q = Queue.Queue()

for i in range(5):
    q.put(i)

while not q.empty():
    print q.get()
#输出为 0,1,2,3,4
- 实现方式二:list列表
  • 添加元素:q.append(data)
  • 弹出元素:q.pop(0)
q = []

for i in range(5):
    q.append(i)

while not len(q):
    print q.pop(0)	#弹出首位元素
#输出为 0,1,2,3,4
- 实现方式三:collections下的deque

是一个双向队列,可以当队列使用也可以当栈使用

  • 添加元素:q.append(data)
  • 弹出元素:q.popleft()
from collections import deque
q = deque()

for i in range(5):
    q.append(i)

while not q.empty():
    print q.popleft()	#弹出首位元素
#输出为 0,1,2,3,4

- Queue的LIFO队列
  • 添加元素:q.put(data)
  • 弹出元素:q.get()
import Queue

q = Queue.LifoQueue()

for i in range(5):
    q.put(i)

while not q.empty():
    print q.get()
#输出为 4,3,2,1,0
- 实现方式二:list列表
  • 添加元素:q.append(data)
  • 弹出元素:q.pop()
q = []

for i in range(5):
    q.append(i)

while not len(q):
    print q.pop()	#弹出末尾元素
#输出为 4,3,2,1,0
- 实现方式三:deque
  • 添加元素:q.append(data)
  • 弹出元素:q.pop()
from collections import deque
q = deque()

for i in range(5):
    q.append(i)

while not q.empty():
    print q.pop()	#弹出末尾元素
#输出为 4,3,2,1,0

- 小顶堆:heapq
import heapq

heap = [] #创建了一个空堆 
heapq.heappush(heap,item) #往堆中插入一条新的值,先添加到列表最后再从下至上调整堆sift-up
item = heapq.heappop(heap) #从堆中弹出最小值, 将最后一个元素放到首位并从上至下调整堆sift-down 
item = heap[0] #查看堆中最小值,不弹出 
heapq.heapify(list) #以线性时间将一个列表转化为堆,对列表做了修改 
heapq.heappushpop(heap,item) #等价于高效的push+pop。如果item小于堆顶元素则实际上堆的结构不变并返回的就是item,否则弹出原堆顶元素
item = heapq.heapreplace(heap,item) #删除并返回最小元素值,添加新的元素值
  • 如果想实现维护一个最大的K个数的堆的功能 --> 容量为k的小顶堆
  • heappushpop( )heappush( ) + heappop( )快的原因在于:heappush( ) + heappop( )调整两次堆,而heappushpop( )会先做判断,如果推入值小于等于堆顶则不对堆做修改,只有大于时才将堆顶元素置换成新值并调整一次堆
  • heappushpop( )heapreplace( )的区别:heappushpop( )会pop的是“推入”后的最小值,如果val比堆顶元素大,则返回堆顶值,并调整堆,否则返回val。而heapreplace( )是强行将堆顶元素替换成val,并返回原堆顶元素值,返回的是“推入”前的最小值,并调整堆。
- 大顶堆:heapq( )+对所有元素取反

由于heapq只支持最小堆,因此若想实现最大堆,可以人为将所有元素取负,这样维护一个负值的最小堆就等价于维护原值的最大堆,之后又需求弹出时再取负还原原值

  • 如果想实现维护一个最小的K个数的堆的功能 --> 容量为k的大顶堆 --> 针对负值的小顶堆(即针对原值负值的最大的K个数

Python的and和or的返回值


>>> 'a' and 'b'
'b'
>>> '' and 'b'
''
>>> 'a' and 'b' and 'c'

>>> 'a' or 'b'
'a'
>>> '' or 'b'
'b'
>>> '' or ''
''

and的演算规则:

  1. and运算时,从左到右演算表达式的值。0, ‘’, [], {}, None在布尔表达式环境下为假,其他任何东西都为真
  2. 如果and运算中,所有的值都为真,那么and返回最后一个值。如:‘a’ and ‘b’
  3. 如果某个值为假,那么and立即返回该假值(短路运算),如:’’ and ‘b’

or的演算规则:

  1. 从左到右演算

  2. 如果有一个值为真,立即返回该值

  3. 所有所有的值都为假,返回最后一个假值

sort自定义排序规则

python2.×的版本中,sort有cmp参数,可以接收两个值自定义比较规则。但python3.×版本就取消了cmp,但可以通过functools实现相同的功能。【升序排列的规则:如果 认为a>b则返回正数,小于则返回负数,相等则返回0】
需求源自:JZ45 把数组排成最小的数
参考:python的sort函数python3 为什么取消了sort方法中的cmp参数?

def cmp(a, b):
	return int(str(a)+str(b)) - int(str(b)+str(a))
	# 升序排列的规则:如果 认为a>b则返回正数,小于则返回负数,相等则返回0
	
iterable.sort(cmp=None, key=None, reverse=False)   #python 2.x
iterable.sort(key=None, reverse=False)   #python 3.x

sorted(iterable, cmp=None, key=None, reverse=False)        #python 2.x
sorted(iterable, key=None, reverse=False)          #python 3.x
# 由此可看出, Python 3.x 取消了 cmp 参数, 所以如果想给 sorted()函数传参的话, 就剩下 key

###  python3.×
from functools import cmp_to_key

iterable.sort(key=cmp_to_key(cmp))
sorted(iterable, key=cmp_to_key(cmp))
sorted(iterable, key=cmp_to_key(lambda a,b : int(str(a)+str(b)) - int(str(b)+str(a))))	#或直接用匿名函数定义cmp

python中All的使用

all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。可以缩减一个循环,使代码简洁。

元素除了是 0、空、None、False 外都算 True。
等价于:

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True
  
  
>>> all(['a', 'b', 'c', 'd'])  # 列表list,元素都不为空或0
True
>>> all(['a', 'b', '', 'd'])   # 列表list,存在一个为空的元素
False
>>> all([0, 12, 3])          # 列表list,存在一个为0的元素
False
>>> all([])             # 空列表
True
>>> all(())             # 空元组
True

python中chain的使用

itertools.chain() 方法可以用来拼接多个迭代对象。 它接受一个可迭代对象列表作为输入,
并返回一个迭代器。可以优雅地将多个循环合并为一个。

>>> from itertools import chain
>>> a = [1, 2, 3, 4]
>>> b = ['x', 'y', 'z']
>>> for x in chain(a, b):
... print(x)
...
1
2
3
4
x
y
z
# 对矩阵的行和列都执行一次循环,可以用chain:
for row in chain(matrix, zip(*matrix)

简化代码系列

  • 对二维列表的遍历,双重循环—>单层循环 的小技巧:
# 双重
row, col = 5, 6
for i in range(row):
	for j in range(col):
		print(i,j)

#单层:使用列表生成器
for i,j in [(i,j) for i in range(row) for j in range(col)]:
    print(i,j)


# 单层:对元素遍历
[array[i][j] for i in range(row) for j in range(col)]]
# 或:
[ele for hang in array for ele in hang]
  • 二维列表求和
# 注意对于二维列表,不能直接sum(array)
# 低级版
sum(sum(listele) for listele in array)
# 高级版   map(fun, obj)相当于对后面一个可迭代对象obj的每一次迭代[即列表中的每一行]执行fun[即sum]操作,返回值是一个列表。然后外层再对每一行的和求和。
sum(map(sum, array))

大杂烩

判断一个数是否为整数: int(a) == a

注意事项

列表如果是在边遍历边删除满足某条件的元素的情况下,要从后往前遍历。否则会导致遍历不完全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值