07基本数据类型---集合

唯一的、不可变对象的无序集合,支持与数学集合理论相对应的操作

集合的操作很像一个无值的字典
由于集合是无序的,并且不会把键匹配到值,因此,集合既不是序列也不是映射类型,它们是自成一体的类型
由于是无序的,因此不支持索引和切片这样的操作
集合只能包含不可变(即可散列的)的对象类型,因此,字典和列表不能嵌入到集合中,集合也不能嵌入到集合中,但是元组是可以嵌入的
集合是可迭代容器,支持len(),for循环和列表解析这样的操作

1、集合的创建

x = set((1,2,3))    #接收一个序列或可迭代对象
y = set()           #创建空集合必须这样创建
z = {1,2,3}

 2、支持一般的数学集合运算

x = set('abcde')  # {'a', 'e', 'c', 'b', 'd'}
print('a' in x)  # True
print(x - y)  # {'b', 'e', 'd'}
print(x.add('m'))  # None
print(x)  # {'a', 'd', 'm', 'c', 'e', 'b'}
x.add((1,)) # 可以添加元组
x.add([1]) #会报错,TypeError: unhashable type: 'list',字典和列表不能嵌入到集合中
print(x.remove('a'))  # None
print(x)  # {'d', 'c', 'b', 'e', 'm'}

 3、集合解析

x = {i**2 for i in [1,2,3,4]} #{16, 1, 4, 9}

 4、集合应用

# 1.可以用来把一些重复项从其他集合中过滤掉
# 2.当遍历图或环结构时,可以记录已访问过的位置
# 3.处理较大的数据集合时,两个集合的交集包含了两个领域的共同对象,并集包含了所有的项目。

 练习1:关系运算

  有如下两个集合,pythons是报名python课程的学员名字集合,linuxs是报名linux课程的学员名字集合
  pythons={'alex','egon','yuanhao','wupeiqi','gangdan','biubiu'}
  linuxs={'wupeiqi','oldboy','gangdan'}
  1. 求出既报名python又报名linux课程的学员名字集合
  2. 求出所有报名的学生名字集合
  3. 求出只报名python课程的学员名字
  4. 求出没有同时这两门课程的学员名字集合

pythons = {'alex','egon','cc','dd','biubiu'}
linuxs = {'egon','cc'}
python_and_linux = pythons & linuxs
python_or_linux = pythons | linuxs
python_only = pythons - linuxs
one_only = pythons ^ linuxs  #^对称差集:返回两个集合中不重复的元素
print(one_only)

 练习2:去重

   1. 有列表l=['a','b',1,'a','a'],列表元素均为可hash类型,去重,得到新列表,
且新列表无需保持列表原来的顺序
   2.在上题的基础上,保存列表原来的顺序
   3.去除文件中重复的行,肯定要保持文件内容的顺序不变
   4.有如下列表,列表元素为不可hash类型,去重,得到新列表,且新列表一定要保持列表原来的顺序
l=[
{'name':'egon','age':18,'sex':'male'},
{'name':'alex','age':73,'sex':'male'},
{'name':'egon','age':20,'sex':'female'},
{'name':'egon','age':18,'sex':'male'},
{'name':'egon','age':18,'sex':'male'},
]
# 1.新列表无需保持列表原来的顺序
l=['a','b',1,'a','a']
l = list(set(l))
print(l)  #[1, 'a', 'b']

# 2.保存列表原来的顺序

# 方法1:不利用集合
l=['a','b',1,'a','a']
new_l = []
for i in l:
    if i not in new_l:
        new_l.append(i)
print(new_l)


# 方法2:利用集合
l=['a','b',1,'a','a']
s = set()
new_l = []
for i in l:
    if i not in s: #利用集合判断是否是重复的元素,如果不是重复的则在下面的列表里进行添加
        s.add(i)
        new_l.append(i) #注意这里是new_l添加元素
print(new_l)


# 方法3:利用集合+列表排序
l=['a','b',1,'a','a']
new_l = list(set(l)) #此时改变了顺序
new_l.sort(key=l.index) #将list2中的元素按照list1中元素出现的顺序排序
print(new_l)

3.去除文件中重复的行,肯定要保持文件内容的顺序不变

new_lines = []
with open('set_file.txt', 'r') as f_read,open('set_file.txt', 'w') as f_write:
    lines = f_read.readlines()
    for line in lines:
        if line not in new_lines:
            new_lines.append(line)
    for line in new_lines:
        f_write.write(line)

 4.有如下列表,列表元素为不可hash类型,去重,得到新列表,且新列表一定要保持列表原来的顺序

#集合元素必须是不可变类型,字典是可变元素

l = [
    {'name': 'egon', 'age': 18, 'sex': 'male'},
    {'name': 'alex', 'age': 73, 'sex': 'male'},
    {'name': 'egon', 'age': 20, 'sex': 'female'},
    {'name': 'egon', 'age': 18, 'sex': 'male'},
    {'name': 'egon', 'age': 18, 'sex': 'male'},
]

# (1)方法1:将字典元素转变为元组添加到set中
s = set()
new_l = []
for i in l:
    # 集合不可添加字典元素,先将其转变为元组
    val = (i['name'],i['age'],i['sex'])
    if val not in s:
        s.add(val)
        # 这里自己开始写的是new_l.append(val),等到的结果是列表里元组
        # new_l.append(val)
        new_l.append(i)
print(new_l)


#(2)方法2:定义函数,既可以针对可以hash类型又可以针对不可hash类型
def func(items, key=None):
    s = set()
    for item in items:
        # 这里Key(item)就是得到字典中的值,传入的key是一个Lambda定义的函数,根据Key返回value
        val = item if key is None else key(item) #和方法1思想一样,也是转换为元组
        if val not in s:
            s.add(val)
            yield item

new_l = list(func(l,key=lambda dic:(dic['name'],dic['age'],dic['sex'])))
print(new_l)

 

posted @ 2021-04-03 17:48  cheng4632  阅读(191)  评论(0编辑  收藏  举报