机器之心合集
参赛:极客艾、思源
一般我们都比较熟悉列表、元组、字典等数据结构,但是集合可能用得稍微少一些。 然而,集合独特的元素唯一性和O(1)时间复杂度的成员检测方法使其在许多任务中具有特殊的优势。 本文介绍了集合的常用方法和概念,包括集合元素的操作、基本集合操作和不可变集合。
理解集合:它们是什么、如何创建它们、何时使用它们、内置函数是什么以及它们与集合理论运算的关系
集合、列表和元组
列表和元组是按序列存储值的标准数据类型。 集合是另一种标准数据类型,也可用于存储值。 它们之间的主要区别在于集合不同于列表或元组。 集合中的每个元素不能出现多次并且无序存储。
收藏优势
由于集合中的元素不能多次出现,这使得集合可以有效地从列表或元组中删除重复值,并执行常见的数学运算,例如并集和交集。
本教程将向您介绍一些有关集合和集合论的主题:
有了这个大纲,我们就开始吧。
集合初始化
集合是一种可变数据组织,具有某些(唯一)、不可变的元素,并且元素是无序的。
您可以使用“set()”操作初始化一个空集。
emptySet = set()
如果要使用值初始化集合,可以将列表传递给“set()”。
dataScientist = set(['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'])
dataEngineer = set(['Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'])
如果你查看上面“”和“”集合中的变量,你会发现集合中元素值的顺序与它们添加的顺序不同。 这是因为集合是无序的。
集合中包含的值也可以使用花括号进行初始化。
dataScientist = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'}
dataEngineer = {'Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'}
请记住,花括号只能用于初始化包含值的集合。 如下图所示,使用不包含值的花括号是初始化字典(dict)而不是集合的一种方法。
从集合中添加或删除值
要向集合中添加或删除值,必须首先初始化集合。
# Initialize set with values
graphicDesigner = {'InDesign', 'Photoshop', 'Acrobat', 'Premiere', 'Bridge'}
为收藏增值
您可以使用“add”方法向集合添加值。
graphicDesigner.add('Illustrator')
需要注意的一件事是,您只能将不可变值(例如字符串或元组)添加到集合中。 例如,如果您尝试将列表添加到集合中,系统将返回类型错误“”。
graphicDesigner.add(['Powerpoint', 'Blender'])
从集合中删除值
有多种方法可以从集合中删除值:
选项 1:您可以使用 "" 方法从集合中删除值。
graphicDesigner.remove('Illustrator')
这种方法的一个缺点是,如果要删除集合中不存在的值,系统将返回一个关键错误“”。
选项 2:您可以使用 "" 方法从集合中删除值。
graphicDesigner.discard('Premiere')
该方法相对于“”方法的优点是,如果尝试删除集合中不存在的值,系统将不会返回“”。 如果您熟悉字典(dict)数据结构,您可能会发现此方法类似于字典的“get”方法的工作模式。
选项 3:您还可以使用“pop”方法从集合中删除并返回任意值。
graphicDesigner.pop()
需要注意的是,如果集合为空,该方法将返回一个“”。
删除集合中所有值
您可以使用“clear”方法删除集合中的所有值。
graphicDesigner.clear()
迭代集合
与许多标准数据类型一样,用户可以迭代集合。
# Initialize a set
dataScientist = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'}
for skill in dataScientist:
print(skill)
如果仔细查看“”集合中打印的每个值,您会发现集合中的值打印的顺序与添加的顺序不同。
使集合中的值排序
本教程向大家强调了集合是无序的。 如果您认为需要以有序形式从集合中获取值,可以使用“”函数,它将输出一个有序列表。
type(sorted(dataScientist))
以下代码按字母降序顺序输出“”集合中的值(本例中为 ZA)。
sorted(dataScientist, reverse = True)
从列表中删除重复项
首先我们必须强调,集合是从列表中删除重复值的最快方法。 为了证明这一点,我们来看看下面两种方法之间的差异。
方法一:使用集合从列表中删除重复值。
print(list(set([1, 2, 3, 1, 7])))
方法2:使用列表推导式(list)从列表中删除重复值。
def remove_duplicates(original):
unique = []
[unique.append(n) for n in original if n not in unique]
return(unique)
print(remove_duplicates([1, 2, 3, 1, 7]))
性能差异可以使用“”库来测量,它允许您对代码进行计时。 以下代码运行每个方法 10,000 次并打印总时间(以秒为单位)。
import timeit
# Approach 1: Execution time
print(timeit.timeit('list(set([1, 2, 3, 1, 7]))', number=10000))
# Approach 2: Execution time
print(timeit.timeit('remove_duplicates([1, 2, 3, 1, 7])', globals=globals(), number=10000))
比较两种方法,结果表明使用集合去除重复值的效率更高。 尽管时间差看起来很小,但当您的列表非常大时,它实际上可以节省您很多时间。
设置操作方法
常用的集合方法执行标准数学运算,例如并集、交集、差集和对称差集。 下图显示了对集合 A 和集合 B 执行的一些标准数学运算。每个维恩图中的红色部分是给定集合运算的结果。
集合具有允许您执行这些数学运算的方法,以及可以为您提供等效结果的运算符。 在研究这些方法之前,我们首先初始化两个集合“”和“”。
dataScientist = set(['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'])
dataEngineer = set(['Python', 'Java', 'Scala', 'Git', 'SQL', 'Hadoop'])
联盟
表示为“ ∪ ”的并集是属于“ ”或“ ”或两者的元素集合。 您可以使用“union”方法来查找两个集合中的所有唯一值。
# set built-in function union
dataScientist.union(dataEngineer)
# Equivalent Result
dataScientist | dataEngineer
并集运算返回的集合可以可视化为下面维恩图中的红色部分。
路口
集合“”和“”的交集可以表示为“∩”,它是同时属于这两个集合的所有元素的集合。
# Intersection operation
dataScientist.intersection(dataEngineer)
# Equivalent Result
dataScientist & dataEngineer
交集运算返回的集合可以可视化为下面维恩图中的红色部分。
您可能会发现遇到需要确保两个集合没有共同值的情况。 换句话说,您想要获得交集为空的两个集合。 这两个集合称为互斥集合。 可以使用“”方法测试两个集合是否互斥。
# Initialize a set
graphicDesigner = {'Illustrator', 'InDesign', 'Photoshop'}
# These sets have elements in common so it would return False
dataScientist.isdisjoint(dataEngineer)
# These sets have no elements in common so it would return True
dataScientist.isdisjoint(graphicDesigner)
您会注意到,在下面维恩图所示的交集中,“ ”和“ ”没有共同值。
差异集
集合“”和“”的差集可以表示为“\”,即属于“”但不属于“”的所有元素的集合。
# Difference Operation
dataScientist.difference(dataEngineer)
# Equivalent Result
dataScientist - dataEngineer
差分运算返回的结果可以可视化为下面维恩图中的红色部分。
对称集
“”和“”的对称集合,表示为“△”,是属于两个集合但不属于两个集合的公共部分的集合。
# Symmetric Difference Operation
dataScientist.symmetric_difference(dataEngineer)
# Equivalent Result
dataScientist ^ dataEngineer
对称集合运算返回的结果可以可视化为下面维恩图中的红色部分。
集合推导
您之前可能已经了解过列表推导式 ( list )、字典推导式 ( ) 和生成器推导式。 还有一个集合推导(Set)。 集合推导与它们非常相似。 中的集合推导可以构造如下:
{skill for skill in ['SQL', 'SQL', 'PYTHON', 'PYTHON']}
上面的输出是一个包含2个值的集合,因为相同的元素不能在集合中出现多次。 使用集合推导式背后的动机是希望能够在代码中编写和导出表达式,而无需手动进行数学计算。
{skill for skill in ['GIT', 'PYTHON', 'SQL'] if skill not in {'GIT', 'PYTHON', 'JAVA'}}
上面的代码和你之前学过的差异集类似,但是看起来有些不同。
会员检测
成员资格测试检查序列中是否包含特定元素,例如字符串、列表、元组或集合。 在 中使用集合的一个主要优点是它们针对 中的成员资格检测进行了深度优化。 例如,对集合进行成员检查比对列表进行检查要高效得多。 如果你是计算机科学专业的学生,我们可以说这是因为集合中成员检测的平均时间复杂度是 O(1),而列表中成员检测的平均时间复杂度是 O(n)。
下面的代码展示了使用列表进行成员检测的过程:
# Initialize a list
possibleList = ['Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS', 'Java', 'Spark', 'Scala']
# Membership test
'Python' in possibleList
集合中也可以进行类似的操作,但集合效率更高。
# Initialize a set
possibleSet = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS', 'Java', 'Spark', 'Scala'}
# Membership test
'Python' in possibleSet
由于“”是一个集合,而“”是集合“”中的元素,因此可以表示为“' ε ”。 如果有一个不属于该集合的值,例如“”,则可以表示为“'∉”。
子集
事实上,集合的成员和成员的组合都是子集。 让我们首先初始化这两个集合。
possibleSkills = {'Python', 'R', 'SQL', 'Git', 'Tableau', 'SAS'}
mySkills = {'Python', 'R'}
如果集合“”中的每个值都属于集合“”,则“”称为“”的子集,数学上写为“⊆”。 您可以使用“”方法来检查一个集合是否是另一个集合的子集。
mySkills.issubset(possibleSkills)
因为在这个例子中,这个方法返回“True”。 在下面的维恩图中,请注意“”中的每个值也在集合“”中。
不可变集
我们经常看到嵌套的列表或元组,其元素可能是另一个列表或元组。
# Nested Lists and Tuples
nestedLists = [['the', 12], ['to', 11], ['of', 9], ['and', 7], ['that', 6]]
nestedTuples = (('the', 12), ('to', 11), ('of', 9), ('and', 7), ('that', 6))
嵌套集合的问题在于,集合一般不能包含集合等可变值。 在这种情况下,您可能需要使用不可变的 set()。 不可变集与可变集非常相似,只是值不能更改。 您可以使用“()”创建不可变集。
# Initialize a frozenset
immutableSet = frozenset()
如果您使用如下所示的不可变集,则可以创建嵌套集合。
nestedSets = set([frozenset()])
重要的是要记住,不可变集的一个主要缺点是,由于它们是不可变的,这意味着您无法向其中添加元素或从中删除元素。
结论
套装非常有用。 它们可以有效地从列表等数据结构中删除重复值,并执行常见的数学运算,例如并集和交集。 人们经常遇到的一个挑战是何时使用各种数据类型,例如何时使用集合或字典。 作者希望本文能够演示基本的集合概念,并帮助我们在不同的任务中使用不同的数据类型。
原文链接: