跳到主要内容

Python集合知识

基础知识

集合的性质

  1. 无序性:集合中的元素没有特定的顺序。
  2. 唯一性:集合中的每个元素都是唯一的,不允许重复。
  3. 可变性:集合本身是可变的,可以添加和删除元素,但集合中的元素必须是不可变的(例如,数字、字符串、元组)。

创建集合

可以使用大括号 {}set() 函数来创建集合。

# 使用大括号创建集合
my_set = {1, 2, 3, 4, 5}
print(my_set) # 输出: {1, 2, 3, 4, 5}

# 使用 set() 函数创建集合
my_set = set([1, 2, 3, 4, 5])
print(my_set) # 输出: {1, 2, 3, 4, 5}

# 创建空集合(必须使用 set(),不能使用 {})
empty_set = set()
print(empty_set) # 输出: set()

添加和删除元素

集合支持添加和删除元素的方法。

my_set = {1, 2, 3}

# 添加元素
my_set.add(4)
print(my_set) # 输出: {1, 2, 3, 4}

# 删除元素
my_set.remove(2)
print(my_set) # 输出: {1, 3, 4}

# 使用 discard() 方法删除元素(如果元素不存在,不会报错)
my_set.discard(5) # 不会报错
print(my_set) # 输出: {1, 3, 4}

# 使用 pop() 方法删除任意一个元素
popped_element = my_set.pop()
print(popped_element) # 输出: 1(集合是无序的,弹出的元素不确定)
print(my_set) # 输出: {3, 4}

# 清空集合
my_set.clear()
print(my_set) # 输出: set()

集合运算

集合支持多种运算,如并集、交集、差集、对称差集等。

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# 并集
union_set = set1 | set2
print(union_set) # 输出: {1, 2, 3, 4, 5, 6}

# 交集
intersection_set = set1 & set2
print(intersection_set) # 输出: {3, 4}

# 差集
difference_set = set1 - set2
print(difference_set) # 输出: {1, 2}

# 对称差集
symmetric_difference_set = set1 ^ set2
print(symmetric_difference_set) # 输出: {1, 2, 5, 6}

集合的其他方法

集合还支持一些其他的方法和操作。

my_set = {1, 2, 3}

# 测试元素是否在集合中
print(2 in my_set) # 输出: True
print(4 in my_set) # 输出: False

# 长度
print(len(my_set)) # 输出: 3

# 拷贝集合
another_set = my_set.copy()
print(another_set) # 输出: {1, 2, 3}

# 更新集合(添加多个元素)
my_set.update([4, 5, 6])
print(my_set) # 输出: {1, 2, 3, 4, 5, 6}

# 集合推导式
squared_set = {x**2 for x in range(1, 6)}
print(squared_set) # 输出: {1, 4, 9, 16, 25}

集合与不可变集合(frozenset)

除了可变集合(set),Python 还提供了不可变集合(frozenset),一旦创建就不能修改。

# 创建不可变集合
immutable_set = frozenset([1, 2, 3, 4])
print(immutable_set) # 输出: frozenset({1, 2, 3, 4})

# 不可变集合不能修改
# immutable_set.add(5) # 这行代码会报错

# 但可以进行集合运算
another_set = frozenset([3, 4, 5, 6])
print(immutable_set | another_set) # 输出: frozenset({1, 2, 3, 4, 5, 6})

小结

  • 创建集合:使用 {}set()
  • 添加元素:使用 add()
  • 删除元素:使用 remove()discard()pop()
  • 集合运算:并集(|)、交集(&)、差集(-)、对称差集(^)。
  • 其他方法inlen()copy()update()、集合推导式。
  • 不可变集合:使用 frozenset

集合的应用

1. 去重

集合的一个主要应用是去重,因为集合本身不允许重复元素。这在数据处理中非常有用。

# 去重示例
data = [1, 2, 2, 3, 4, 4, 5]
unique_data = list(set(data))
print(unique_data) # 输出: [1, 2, 3, 4, 5]

2. 查找唯一元素

集合查找元素的时间复杂度是 (O(1)),这使得它非常适合用于快速查找。

# 查找唯一元素示例
unique_elements = {1, 2, 3, 4, 5}
print(3 in unique_elements) # 输出: True
print(6 in unique_elements) # 输出: False

3. 集合运算

集合运算(并集、交集、差集、对称差集)在许多算法中都有应用。例如,求两个集合的共同元素、不同元素等。

# 集合运算示例
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# 并集
union = set1 | set2
print(union) # 输出: {1, 2, 3, 4, 5, 6}

# 交集
intersection = set1 & set2
print(intersection) # 输出: {3, 4}

# 差集
difference = set1 - set2
print(difference) # 输出: {1, 2}

# 对称差集
symmetric_difference = set1 ^ set2
print(symmetric_difference) # 输出: {1, 2, 5, 6}

4. 词汇去重与统计

在自然语言处理(NLP)和文本分析中,集合可以用于去重和统计唯一单词。

# 词汇去重与统计示例
text = "this is a test. this test is only a test."
words = text.split()
unique_words = set(words)
print(unique_words) # 输出: {'a', 'is', 'only', 'this', 'test.', 'test'}

# 统计唯一单词数量
print(len(unique_words)) # 输出: 6

5. 图算法中的应用

在图算法中,集合常用于表示节点的邻居、访问过的节点等。例如,深度优先搜索(DFS)和广度优先搜索(BFS)中使用集合来跟踪访问过的节点。

# 图算法中的集合应用示例
graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
}

# 深度优先搜索(DFS)
def dfs(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
print(start, end=' ')
for next in graph[start]:
if next not in visited:
dfs(graph, next, visited)

dfs(graph, 'A') # 输出: A B D E F C

# 广度优先搜索(BFS)
from collections import deque

def bfs(graph, start):
visited = set()
queue = deque([start])
while queue:
vertex = queue.popleft()
if vertex not in visited:
visited.add(vertex)
print(vertex, end=' ')
queue.extend([node for node in graph[vertex] if node not in visited])

bfs(graph, 'A') # 输出: A B C D E F

6. 集合覆盖问题

集合覆盖问题是经典的 NP 完全问题之一,常用于优化和组合问题。例如,选取最少的集合覆盖所有元素。

# 集合覆盖问题示例
universe = {1, 2, 3, 4, 5}
subsets = [{1, 2, 3}, {2, 4}, {3, 4, 5}, {5}]

def greedy_set_cover(universe, subsets):
covered = set()
cover = []
while covered != universe:
subset = max(subsets, key=lambda s: len(s - covered))
cover.append(subset)
covered |= subset
return cover

cover = greedy_set_cover(universe, subsets)
print(cover) # 输出: [{1, 2, 3}, {3, 4, 5}]

7. 数据库操作中的集合

在数据库查询中,集合操作(如交集、并集、差集)常用于处理查询结果。

# 数据库操作中的集合示例
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

# 查询结果的交集
common_results = set1 & set2
print(common_results) # 输出: {3, 4}

8. 排列组合问题

在排列组合问题中,集合用于生成不重复的组合和排列。

# 排列组合问题示例
from itertools import combinations

items = {1, 2, 3}
all_combinations = list(combinations(items, 2))
print(all_combinations) # 输出: [(1, 2), (1, 3), (2, 3)]

Questions

Q1

如果我使用add方法添加一个集合中已经存在的元素,集合会发生什么?

在 Python 中,集合(set)是一种无序且不重复的元素集合。如果你使用 add 方法向集合中添加一个已经存在的元素,集合不会发生任何变化。集合会自动处理重复元素,确保每个元素在集合中只出现一次。

以下是一个示例代码,展示了向集合中添加已存在的元素时的行为:

# 创建一个集合
my_set = {1, 2, 3}

# 打印集合
print("原始集合:", my_set)

# 尝试添加一个已经存在的元素
my_set.add(2)

# 打印集合,观察是否有变化
print("添加已存在元素后的集合:", my_set)

# 尝试添加一个新元素
my_set.add(4)

# 打印集合,观察是否有变化
print("添加新元素后的集合:", my_set)

输出结果将是:

原始集合: {1, 2, 3}
添加已存在元素后的集合: {1, 2, 3}
添加新元素后的集合: {1, 2, 3, 4}

从输出中可以看到,当我们尝试添加已经存在的元素 2 时,集合没有发生变化。而当我们添加一个新的元素 4 时,集合中成功添加了这个新元素。

总结来说,使用 add 方法向集合中添加一个已经存在的元素不会引起任何变化,因为集合会自动忽略重复的元素。