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

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

集合对象的创建与删除

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

    >>> a = {3,5}
    >>> type(a)
    <class 'set'>
  • 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 "<stdin>", line 1, in <module>
    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 "<stdin>", line 1, in <module>
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)
    ...
    <class 'dict'> time used: 0.865715503692627
    <class 'set'> time used: 0.9040701389312744
    <class 'tuple'> time used: 487.52976393699646
    <class 'list'> 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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
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 "<stdin>", 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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1
SyntaxError: starred assignment target must be in a list or tuple

Python序列结构--集合的更多相关文章

  1. Python序列结构

    python中常用的序列结构由列表.元组.字典.字符串.集合等,列表.元组.字符串等有序序列以及range对象均支持双向索引 是否有序 序列结构 是否是可变序列 有序序列 元组 不可变序列 有序序列 ...

  2. python 序列结构-列表,元组,字典,字符串,集合

    列表 """ name_list.__add__( name_list.__getslice__( name_list.__new__( name_list.append ...

  3. Python序列结构--列表(一)

    列表 列表**包含若干元素的有序连续内存空间**,当列表增加或删除元素时,**列表对象自动进行内存的扩展或收缩**,从而**保证相邻元素之间没有缝隙**.但插入和删除非尾部元素时涉及列表元素大量的移动 ...

  4. Python序列结构--字典

    字典:反映对应关系的映射类型 字典(dict)是包含若干“键:值”元素的无序可变序列 字典中元素的“键”可以是python中任意不可变数据,例如整数.实数.复数.字符串.元组等类型可哈希数据,“键”不 ...

  5. Python序列结构--元组

    元组:轻量级列表 元组创建于元素访问 >>> x = (1, 2, 3)>>> type(x)<class 'tuple'>>>> x ...

  6. [Python笔记][第二章Python序列-tuple,dict,set]

    2016/1/27学习内容 第二章 Python序列-tuple tuple创建的tips a_tuple=('a',),要这样创建,而不是a_tuple=('a'),后者是一个创建了一个字符 tup ...

  7. 【转】Python数据类型之“集合(Sets)与映射(Mapping)”

    [转]Python数据类型之“集合(Sets)与映射(Mapping)” 一.集合类型(Sets) 集合对象是不同的(不可重复)hashable对象的无序集合.常见用法包括:成员关系测试.移除序列中的 ...

  8. 第2章 Python序列

    Python序列类似于C或Basic中的一维.多维数组等,但功能要强大很多,使用也更加灵活.方便,Head First Python一书就戏称列表是“打了激素”的数组. Python中常用的序列结构有 ...

  9. Python序列的切片操作与技巧

    切片操作 对于具有序列结构的数据来说,切片操作的方法是:consequence[start_index: end_index: step]. start_index: 表示是第一个元素对象,正索引位置 ...

随机推荐

  1. Google弃用HttpClient 而推荐使用HttpURLConnection的原因

    因为兼容性问题,谷歌不愿意维护HttpClient,而使用HttpURLConnection HttpURLConnection的API包小而简便,更适合安卓 HttpURLConnection能够提 ...

  2. git常用方法

    一.创建项目 git clone xx.git         克隆项目到本地 git init                     初始化本地项目,生成.git文件 二.创建分支,推送分支,合并 ...

  3. ios 根据 schemes 打开 app

    公司出需求,要让 h5链接直接打开用户的 app,如果没有安装 app 直接跳转到 appStore 这就需要给 app 配置 schemes 即可 1.在Info.plist中 LSApplicat ...

  4. js如何获取点击<li>标签里的内容值

    路:为li对象添加单击事件→事件触发后利用innerHTML获取li的文本.实例演示如下: 1.HTML结构 <ul id="test"> <li>Glen ...

  5. spring与disruptor集成的简单示例[z]

    [z]https://www.jb51.net/article/135475.htm disruptor不过多介绍了,描述下当前的业务场景,两个应用A,B,应用 A 向应用 B 传递数据 . 数据传送 ...

  6. gulp打包普通项目

    第一步:npm init 生成一个page.json第二步建立一个gulpfile.js文件主要是写这个文件 var gulp = require('gulp'), rev = require('gu ...

  7. 十五、Collections.sort(<T>, new Comparator<T>() {})针对字符串排序

    1.排序对象全是字母组成,可以根据ASCII编码表排序 package com.abcd; public class Person{ private String name; private int ...

  8. linux一台服务器配置多个Tomcat

    前提:linux服务器上已经运行多个Tomcat,再去搭建一个Tomcat服务 1.官网下载Tomcat 2.上传到服务器指定一个目录/usr/local/tomcat 3.然后解压tar包,tar ...

  9. Tigase 发送消息的流程源码分析

    XMPP 的<message/>节是使用基本的”push”方法来从一个地方到另一个地方得到消息.因为消息通常是不告知的,它们是一种”fire-and-forget”(发射后自寻目的)的机制 ...

  10. spring boot自定义线程池以及异步处理

    spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...