nocofffe 发表于 2023-8-3 00:09

30Days Python——Day07 Set(集合)

### Days 07 Set(集合)

集合的基本概念是**无序**,且每个**元素是唯一**的,其实也可以将集合看成是字典的键,每个键皆是唯一的。集合的***元素内容***是<a id="集合元素特性">***不可变***</a>的,常见的元素有整数、浮点数、字符串、元组等。至于可变的内容如列表、字典、集合等不可以是集合元素。但***集合本身是可变***的,我们可以增加或删除集合的元素。

#### 7.0 集合的定义

集合由元素组成’基本概念是无序且每个**元素**是**唯一**(不会重复)的。例如:-个骰子有6面,每一面有一个数字,每个数字是一个元素,我们可以使用集合代表这6个数字。

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

PS:集合的唯一性可以将大量重复的数据删除。

#### 7.1 集合的建立

python中可以使用大括号{ }建立集合,也可以使用set()函数建立集合,但该函数的参数只能有一个元素,可以是字符串、列表、元组、字典等。

```python
empty_dict = {}
print("打印类别 = ",type(empty_dict))
empty_set = set()
print("打印类别 = ",type(empty_set))
# 打印类别 =<class 'dict'>
# 打印类别 =<class 'set'>
```

#### 7.2 集合的操作

| Python符号 |   说明   |
| :--------: | :------: |
|   &      |   交集   |
|   \|   |   并集   |
|   -      |   差集   |
|   ^      | 对称差集 |
|   ==   |   等于   |
|   !=   |不等于|
|   in   |是成员|
|   not in   | 不是成员 |

下面举例介绍几个操作

#### 7.2.1 差集(difference)

有A和B两个集合,如果想获得属于A集合同时不属于B集合的元素, 则可以使用差集(B-A)。

在Python语言中差集的符号是-,另外也可以使用difference()方法完成这个工作。

```python
math ={"A", "B", "C"}         #假设参加数学夏令营的有ABC三人
physics ={"D", "B", "E"}      #假设参加物理夏令营的有DBE三人
math_only = math - physics
print("参加数学夏令营的同时没有参加物理夏令营的成员{}".format(math_only))
```

#### 7.2.2 对称差集(symmetric difference)

有A和B两个集合,如果想获得属于A***或***B集合的元素,但是排除同时属于A*******和***B的元素,则可以使用对称差集。

在Python语言中对称差集的符号是^,另外也可以使用symmetric_difference()方法完成这个工作。

```python
math ={"A", "B", "C"}         #假设参加数学夏令营的有ABC三人
physics ={"D", "B", "E"}      #假设参加物理夏令营的有DBE三人
print("没有同时参加数学和物理夏令营的成员{}".format(math.symmetric_difference(physics)))
# 没有同时参加数学和物理夏令营的成员{'A', 'E', 'C', 'D'}
```

#### 7.3 适用<a id ="集合方法">集合的方法</a>

|             方法            |                     说明                     |
| :---------------------------: | :------------------------------------------: |
|             add()             |               加一个元素到集合               |
|            clear()            |            删除集合的所有元素            |
|            copy()             |                   复制集合                   |
|      difference_update()      |      删除集合内与另外一个集合重复的元素      |
|   intersection_update()   | 可以使用交集更新集合内容,多个交集用”,“隔开 |
|   intersection_update()   |         可以使用交集更新集合内容         |
| symmetric_difference_update() |         使用对称差集更新集合内容         |
|         update()            |             使用并集更新集合内容             |
|         discard()         |             如果是集合成员则删除             |
|         isdisjoint()          |         如果两个集合没有交集返回Ture         |
|         A.issubset(B)         |          如果A集合是B的子集返回Ture          |
|      A.isupperset(B)      |       如果A集合是B集合的父集则返回Ture       |
|             pop()             | 回传所随机删除的元素,如果是空集则返回False|
|         remove()            |   删除指定元素,如果不存在返回KeyError   |

下面以intersection_update()为例子:

```python
math ={"A", "B", "C"}         #假设参加数学夏令营的有ABC三人
physics ={"D", "B", "E"}      #假设参加物理夏令营的有DBE三人
chemistry ={"B", "G", "E", "H"}
retv_vue = math.intersection_update(physics,chemistry)
print("新的math集合为:{}".format(math))
# 新的math集合为:{'B'}
```



#### 7.4 适用集合的基本函数<a id="集合函数">基本函数</a>操作

|    方法   |                说明                |
| :---------: | :--------------------------------: |
| enumerate() |回传连续整数配对的enumerate对象   |
|    len()    |            元素数量            |
|    max()    |               最大值               |
|    min()    |               最小值               |
|sorted()   | 回传已经排序的列表,集合本身不改变 |
|    sum()    |               求总和               |

#### 7.5 冻结集合

set是可变集合,frozenset是不可变集合,也可直译为冻结集合,这是一个新的类别(class), 只要设定元素后,这个冻结集合就不能再更改了。冻结集合的不可变特性的优点是可以用它作为字典的键(key),也可以作为其他集合的元素。(还记得我们曾提到的[构成字典键的特性](#不能重复),和[集合元素特性](#集合元素特性)吗?)

冻结集合的建立方式是使用frozenset()函数,冻结后不可以用[集合函数](#集合函数)修改集合内容但可以用[部分集合方法](#集合方法)intersection()、difference()、 symmetric_difference()、 copy()、 issubset()、 issuperset()、 isdisjoint()等

#### 7.5 集合生成式

我们在先前的章节己经看过[列表](#列表生成式)和[字典的生成式](#字典生成式)了,其实集合也有生成式,语法如下:

新集合 = { 表达式for表达式in可迭代项目}

```python
A = {n for n in range(1,100,2)}                         #在集合A中产生1到100间隔为2的元素
print(A)
#{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99}
```

在集合生成式中我们可以增加if测试句(可以有多个)。

```python
A = {n for n in range(1,100,2) if n % 3 == 0}         #在集合A中产生1到100间隔为2且能整除3的元素
print(A)
# {33, 3, 99, 69, 39, 9, 75, 45, 15, 81, 51, 21, 87, 57, 27, 93, 63}
```

#### 7.5.1 增加集合的效率

在此前,使用字典生成式记录单词”deepstone“中每个字母出现的次数的[例程](#deepstone)中,“for alphabet in word”循环会造成字母e会处理3次,其实只要将集合概念应用在word中,由于集合不会有重复的元素,所以只要处理一次即可,此时可将上述循环改为:for alphabet in set(wold)即可大大提高程序运行效率!

```python
word = "deepstone"
alphabet = {ch : word.count(ch) for ch in set(word)}
print(alphabet)
# {'n': 1, 'p': 1, 'd': 1, 'o': 1, 'e': 3, 't': 1, 's': 1}
```

#### 7.6 小测试

鸡尾酒是酒精饮料,由基酒和一些饮料调制而成,下列是一些常见的鸡尾酒饮料以及它的配方。

蓝色夏威夷(Blue Hawaii):兰姆酒(Rum)、甜酒(Sweet Wine)、椰奶(Coconut Cream)、菠萝汁(Pineapple Juice)、柠檬汁(Lemon Juice)

姜味莫吉托(Ginger Mojito):兰姆酒(Rum)、姜(Ginger)、薄荷叶(Mint Leaves)、青柠汁(Lime Juice)、姜汁汽水(Ginger Soda)

纽约客(New Yorker):威士忌(Whiskey)、红酒(Red Wine)、柠檬汁(Lemon Juice)、糖水(Sweet Syrup)

血腥玛丽(Bloody Mary):伏特加(Vodka)、柠檬汁(Lemon Juice)、西红柿汁(Tomato Juice)、酸辣酱(Tabasco)、少量盐(Little Salt)

T1. 为上述鸡尾酒建立一个字典,上述字典的键是字符串,也就是鸡尾酒的名称,字典的值是集合,内容是各种鸡尾酒的材料配方。使得程序能够列出含有伏特加的酒;含有柠檬汁的酒;含有兰姆酒但是没有姜的酒;含有柠檬汁但是没有椰奶或是酸辣酱的酒。

```python
cocktail ={
    'Blue Hawaiian' : { 'Rum' , 'Sweet wine' , 'Cream' , 'Pineapple Juice' , 'Lemon Juice' },
    'Ginger Mojito' : {'Rum' , 'Ginger' , 'Hint Leaves ' , 'Lime Juice' , 'Ginger Soda'},
    'New Yorker'    : { "whiskey", 'Red wine' , 'Lemon Juice' , 'Sugar Syrup'},
    'Bloody Mary'   : { 'Vodka' , 'Lemon Juice' , 'Tomato Juice' , 'Tabasco' , 'little Salt' }
}
print("含有伏特加的酒:")
for name,formulas in cocktail.items():      #列出含有伏特加的酒
    if 'Vodka' in formulas:
      print(name)
print("含有柠檬汁的酒:")
for name,formulas in cocktail.items():
    if 'Lemon Juice' in formulas:
      print(name)
print("含有兰姆酒但是没有姜的酒:")
for name,formulas in cocktail.items():
    if "Rum" in formulas and not ("Ginger" in formulas):
      print(name)
print("含有柠檬汁但是没有椰奶或是酸辣酱的酒:")
for name,formulas in cocktail.items():
    if "Lemon Juice" in formulas and not formulas&{'Cream','Tabasco'}:
      print(name)
"""
含有伏特加的酒:
Bloody Mary
含有柠檬汁的酒:
Blue Hawaiian
New Yorker
Bloody Mary
含有兰姆酒但是没有姜的酒:
Blue Hawaiian
含有柠檬汁但是没有椰奶或是酸辣酱的酒:
New Yorker
"""
```

PS:上述程序用in测试指定的鸡尾酒材料配方是否在所回传字典值(value)的formulas集合内,另外程序第最后一个for循环则是将formulas与集合元素‘Cream’、'Tabasco'做交集(&),如果↑formulas内没这些配方,结果会是False,经过not就会是True,则可以打印name。

Zhoupizi 发表于 2023-8-3 09:56

好东西,保存起来学习

nocofffe 发表于 2023-8-3 13:40

Zhoupizi 发表于 2023-8-3 09:56
好东西,保存起来学习

感谢支持!

nocofffe 发表于 2023-8-9 20:05

sgf227 发表于 2023-8-9 15:25
收藏等于学会

哈哈哈哈哈!共同学习
页: [1]
查看完整版本: 30Days Python——Day07 Set(集合)