python常用的序列结构_Python序列结构--集合

集合:元素之间不允许重复

集合属于Python无序可变序列,元素之间不允许重复

集合对象的创建与删除

直接将值赋值给变量即可创建一个集合

>>> a = {3,5}

>>> type(a)

set()函数将列表、元组、字符串、range对象等其他可迭代对象转换为集合,如果原来的数据中存在重复元素,则转换为集合的时候只保留一个;如果原序列或迭代对象中有不可哈希的值,无法转换为集合,抛出异常

>>> a_set=set(range(8,14))

>>> a_set

{8, 9, 10, 11, 12, 13}

>>> b_set = set([0,1,2,3,0,1,2,3,7,8])

>>> b_set

{0, 1, 2, 3, 7, 8}

集合推导式来快速生成集合

>>> {x.strip() for x in ('he ','she ',' I')}

{'I', 'he', 'she'}

>>> import random

>>> x = {random.randint(1,500) for i in range(100)}#生成随机数,自动去除重复的元素

>>> len(x)# 一般而言输出结果会小于100

94

>>> {str(x) for x in range(10)}

{'1', '9', '4', '8', '3', '7', '2', '6', '0', '5'}

集合的操作与运算

集合元素的增加和删除

add()方法可以增加新元素,如果该元素已存在则忽略该操作,不会抛出异常;update()方法合并另外一个集合中的元素到当前集合中,并且自动去除重复元素

>>> s = {1,2,3}

>>> s.add(3)# 添加元素,重复元素自动忽略

>>> s.update({3,4})# 更新字典,自动忽略重复的元素

>>> s

{1, 2, 3, 4}

pop()方法随机删除并返回集合中的一个元素,如果为空则抛出异常;remove()方法删除集合中的元素,如果指定元素不存在则抛出异常;discard()方法从集合中删除一个特定的元素,如果元素不存在则忽略该操作;clear()方法清空集合

>>> s

{1, 2, 3, 4}

>>> s.discard(5)# 删除元素,不存在则忽略该操作

>>> s.remove(5)# 删除元素,不存在则抛出异常

Traceback (most recent call last):

File "", line 1, in

KeyError: 5

>>> s.pop()# 删除并返回元素

1

>>> s

{2, 3, 4}

>>> s.clear()

>>> s

set()

集合运算

内置函数len()、max()、min()、sum()、sorted()、map()、filter()、enumerate()等也适用于集合。另外还支持数学意义上的交集、并集、差集等运算

>>> a_set = set([8,9,10,11,12,113])

>>> a_set

{8, 9, 10, 11, 12, 113}

>>> b_set = {0,1,2,3,7,8}

>>> a_set | b_set# 并集

{0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 113}

>>> a_set.union(b_set)# 并集

{0, 1, 2, 3, 7, 8, 9, 10, 11, 12, 113}

>>> a_set & b_set# 交集

{8}

>>> a_set.intersection(b_set)

{8}

>>> a_set.difference(b_set)# 差集

{9, 10, 11, 12, 113}

>>> b_set.difference(a_set)

{0, 1, 2, 3, 7}

>>> a_set - b_set

{9, 10, 11, 12, 113}

>>> b_set - a_set

{0, 1, 2, 3, 7}

>>> a_set.symmetric_difference(b_set)# 对称差集

{0, 1, 2, 3, 7, 9, 10, 11, 12, 113}

>>> a_set ^ b_set

{0, 1, 2, 3, 7, 9, 10, 11, 12, 113}

>>> x = {1,2,3}

>>> y = {1,2,5}

>>> z = {1,2,3,4}

>>> x < y# 比较集合大小/包含关系

False

>>> x < z # 真子集True>>> y < zFalse>>> z < zFalse>>> z <= z # 子集True>>> x.issubset(y) # 测试是否为子集False>>> x.issubset(z)True>>> x.issubset(x)True

不可变集合frozenset

用法与set基本类似,与set类不同的是,frozenset是不可变集合,没有提供add()、remove()等可以修改集合对象的方法

>>> x = frozenset(range(5))

>>> x

frozenset({0, 1, 2, 3, 4})

>>> x.add(2)

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'frozenset' object has no attribute 'add'

>>> x | frozenset(range(5,10)) # 并集

frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})

>>> x & frozenset(range(4,10))# 交集

frozenset({4})

>>> x - frozenset(range(4,10))# 差集

frozenset({0, 1, 2, 3})

>>> frozenset(range(4)) < frozenset(range(5))# 集合包含关系比较

True

集合应用案例

python字典和集合都使用hash表来存储元素,元素查询速度快,关键字in作用于字典和集合比作用于列表要快得多

>>> import random

>>> x1 = list(range(10000))

>>> x2 = tuple(range(10000))

>>> x3 = set(range(10000))

>>> x4 = dict(zip(range(10000),range(10000)))

>>> r = random.randint(0,9999)

>>> for t in (x4, x3, x2, x1):

...   start = time.time()

...   for i in range(9999999):

...     flag = (r in t)

...   print(type(t),'time used:', time.time() - start)

...

time used: 0.865715503692627

time used: 0.9040701389312744

time used: 487.52976393699646

time used: 488.0697581768036

作为集合快速的具体应用,可以使用集合快速提取序列中单一元素,即提取序列中所有不重复的元素

>>> import random

>>> listRandom = [random.choice(range(1000)) for i in range(100)]

>>> len(listRandom)

100

>>> newSet = set(listRandom)

>>> len(newSet)

95

返回指定范围内一定数量的不重复数字

>>> import random

>>> def randomNumbers(number,start,end):

...   '''使用集合生成number个介于start和end之间的不重复随机数'''

...   data = set()

...   while len(data) < number:

...     element = random.randint(start,end)

...     data.add(element)

...   return data

...

>>> randomNumbers(10,1,1000)

{66, 676, 550, 522, 333, 783, 499, 278, 59, 349}

返回指定范围内一定数量的不重复数字,使用random模块的sample()函数更好一些,但是random模块的sample()函数只支持列表、元组、集合、字符串和range对象,不支持字典以及map、zip、enumerate、filter等惰性求值的迭代对象

>>> import random

>>> random.sample(range(1, 700), 10)# 选取指定分布中选取不重复元素

[340, 489, 623, 121, 550, 632, 19, 531, 626, 591]

下面两段代码用来测试指定列表中是否包含非法数据,很明显第二段用集合的代码效率高一些

>>> import random

>>> lstColor = ('red','green','blue')

>>> colors = [random.choice(lstColor) for i in range(10000)]

>>> for item in colors:

...   if item not in lstColor:

...     print('error:',item)

...     break

...

>>>

>>> if (set(colors) - set(lstColor)):

...   print('error')

...

>>>

使用字典和集合模拟有向图结构,并实现了节点的入度和出度计算

>>> def getDegress(orientedGraph,node):

...   outDegree = len(orientedGraph.get(node,[]))

...   inDegree = sum(1 for v in orientedGraph.values() if node in v)

...   return (inDegree, outDegree)

...

>>> graph = {'a' : set('bcdef'), 'b':set('ce'), 'c':set('d'), 'd': set('e'), 'e':set('f'), 'f':set('cgh'),'g':set('fhi'), 'h':set('fgi'), 'i':set() }

>>> print(getDegress(graph, 'h'))

(2, 3)

>>>

序列解包的多种形式和用法

序列解包是Python中非常重要和常用的一个功能,可以使用非常简洁的形式完成复杂的功能,提高代码的可读性,减少了程序员代码的输入量

>>> x,y,z = 1,2,3

>>> x

1

>>> y

2

>>> z

3

>>> v_tuple = (False,3.5,'exp')

>>> (x,y,z) = v_tuple

>>> m,n,q = v_tuple

>>> m,n,q = range(2)

Traceback (most recent call last):

File "", line 1, in

ValueError: not enough values to unpack (expected 3, got 2)

>>> m,n,q = range(3)# 对range对象进行序列解包

>>> x,y,z = range(4)

Traceback (most recent call last):

File "", line 1, in

ValueError: too many values to unpack (expected 3)

>>> x,y,z = iter([1,2,3])# 使用迭代器对象进行序列解包

>>> x,y,z = map(str,range(3))# 使用可迭代的map对象进行序列解包

>>> x

'0'

>>> y

'1'

>>> x,y =y,x# 交换两个变量的值

>>> x

'1'

>>> y

'0'

序列解包还可用于列表、字典、enumerate对象、filter对象等,对字典使用时,默认是对字典“键”进行操作,如果对“键:值“对进行操作应使用字典的items()方法说明,如果需要对字典”值“进行操作应该使用字典的values()方法明确指定

>>> a = [1,2,3]

>>> b,c,d = a

>>> x,y,z = sorted([1,3,2])

>>> s = {'a':1,'b':2,'c':3}

>>> b,c,d = s.items()

>>> b

('a', 1)

>>> c

('b', 2)

>>> d

('c', 3)

>>> b,c,d = s

>>> b

'a'

>>> c

'b'

>>> d

'c'

>>> b,c,d = s.values()

>>> b

1

>>> c

2

>>> d

3

>>> a,b,c='ABC'

>>> a

'A'

>>> b

'B'

>>> c

'C'

使用序列解包可以很方便地同时遍历多个序列

>>> keys = ['a','b','c','d']

>>> values = [1,2,3,4]

>>> for k,v in zip(keys,values):

...   print((k,v),end=' ')

...

('a', 1) ('b', 2) ('c', 3) ('d', 4) >>>

>>> x = ['a','b','c']

>>> for i,v in enumerate(x):

...   print('The value on position {0} is {1}'.format(i,v))

...

The value on position 0 is a

The value on position 1 is b

The value on position 2 is c

>>> s = {'a':1,'b':2,'c':3}

>>> for k,v in s.items():

...   print((k,v),end=' ')

...

('a', 1) ('b', 2) ('c', 3) >>>

序列解包的另类用法和错误的用法:

>>> print(*[1,2,3])

1 2 3

>>> print(*[1,2,3],4,*(5,6))

1 2 3 4 5 6

>>> *range(4),4

(0, 1, 2, 3, 4)

>>> *range(4)

File "", line 1

SyntaxError: can't use starred expression here

>>> {*range(4),4,*(5,6,7)}

{0, 1, 2, 3, 4, 5, 6, 7}

>>> {'x':1,**{'y':2}}

{'x': 1, 'y': 2}

>>> a,b,c,d = range(3),3

Traceback (most recent call last):

File "", line 1, in

ValueError: not enough values to unpack (expected 4, got 2)

>>> a,b,c,d = *range(3),3

下面的代码看起来与序列解包类型,但严格来说是序列解包的逆运算,与函数的可变长度参数一样,用来接收等号右侧的多个数值

>>> a,*b,c = 1,2,3,4,5

>>> a

1

>>> b

[2, 3, 4]

>>> c

5

>>> a,b,c

(1, [2, 3, 4], 5)

>>> a,*b,c = range(20)

>>> b

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

>>> *b = 1,2,4# 等号左边必须为列表、元组或多个变量

File "", line 1

SyntaxError: starred assignment target must be in a list or tuple

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值