1. 概述

集合set数据结构/数据类型和list类似,都是存储一系列的数据或对象,且可以是各种数据类型的数据。和list最大的区别在于,set是无序的,且set中的元素唯一。

在处理一系列数据时,如果需要剔除重复项,则通常采用set数据类型。

Python中集合set的概念和离散数学中集合的概念是完全一致的,也有交集、并集、子集等各种算法。——当然,日常工作未必会用到所有这些。


2. 参考资料

如下:

https://docs.python.org/2/library/sets.html


3. 常用算法

集合分为可变集合set和不可变集合frozenset,本文(暂)仅讨论可变集合。


3.1 定义一个集合

列表是用一对中括号表示、字典dict是用一对花括号表示、元组是一对圆括号表示,如此,括号被占用完了。没有办法,所以集合的定义较为特殊,用set()来初始化一个集合对象。

下面这个例子是先初始化一个set对象,然后调用add()方法不断增加元素:

>>> s = set()
>>> s
set([])
>>> s.add(1)
>>> s
set([1])
>>> s.add(1)
>>> s
set([1])
>>> s.add(10)
>>> s
set([1, 10])
>>> s.add(5)
>>> s
set([1, 10, 5])
>>>

前面已经提到,和list一样,set对象中的数据类型不要求是完全一样的,示例如下:

>>> s = set()
>>> s.add(1)
>>> s.add("one")
>>> s
set([1, 'one'])
>>>



3.2 用列表来初始化一个集合对象

>>> list = [1, 2, 3, "one", "two", "three"]
>>> s = set(list)
>>> s
set([1, 2, 3, 'three', 'two', 'one'])
>>> 
>>> string = "Hello, world!"
>>> s2 = set(string)
>>> s2
set(['!', ' ', 'e', 'd', 'H', 'l', 'o', ',', 'r', 'w'])
>>>



3.3 增加一个元素

如3.1节的代码,set是用add()方法增加一个元素。

如果要增加多个元素、或者把另外一个集合中的元素添加过来,则使用集合的并集算法。


3.4 集合的无序性

集合中元素的顺序并非按照每个元素添加进去的顺序来排列,如下:

>>> s = set()
>>> s.add(3)
>>> s
set([3])
>>> s.add(1)
>>> s
set([1, 3])
>>> s.add(5)
>>> s
set([1, 3, 5])
>>> 
>>> 
>>> s.clear()
>>> s
set([])
>>> s.add("one")
>>> s.add("two")
>>> s
set(['two', 'one'])
>>> s.add("three")
>>> s
set(['three', 'two', 'one'])
>>>

因为无序这一特征,所以set没有list、string等有序对象的索引表示方法,如:

>>> s = set([1,2,3])
>>> s
set([1, 2, 3])
>>> s[1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object does not support indexing
>>>



3.5 集合元素的个数

计算set对象中元素的格式,使用的是len()函数。——set本身没有len()方法或者size()方法,尽管size()这个名称更加合适(如C++ STL中list、vector)。

>>> s
set([1, 2, 3])
>>> s.len()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'set' object has no attribute 'len'
>>> len(s)
3
>>> s.size()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'set' object has no attribute 'size'
>>> 
>>> len(s)
3
>>>



3.6 遍历元素

和list一样,可以用for来遍历集合中的每一个元素:

>>> s
set([1, 10, 5])
>>> for x in s:
...     print x
...
1
10
5
>>>



3.7 排序

前面已经提到,集合对象的存储是无序的,因此,也没有list对象的sort()方法可供调用。但要从一个set对象得到有序的元素序列,则可以先把set对象转换成list对象,然后调用list对象的sort()方法。

>>> s = set(["first", "second", "three", "four", "five"])
>>> s
set(['four', 'second', 'five', 'three', 'first'])
>>> list_of_s = list(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
>>> del list
>>> list_of_s = list(s)
>>> list_of_s
['four', 'second', 'five', 'three', 'first']
>>> list_of_s.sort()
>>> list_of_s
['first', 'five', 'four', 'second', 'three']
>>>

如果顺着前面的例子一路下来,这里会有异常。因为前面我们有个例子是把list作为一个变量名称,因此需要先del这个对象。然后Python解释器才认为list是关键字/内置函数。


3.8  集合的差

source - target: 从source中删除在target中出现的元素。

>>> source = set(['first', 'second', 'third'])
>>> target = set(['first', 'forth'])
>>> source
set(['second', 'third', 'first'])
>>> target
set(['forth', 'first'])
>>> to_be_removed = source - target
>>> to_be_removed
set(['second', 'third'])
>>>



3.9 并集

并集的运算符号是|。普通的加号(+)是不能用于set对象的。

>>> source = set(['first', 'second', 'third'])
>>> target = set(['first', 'forth'])
>>> source
set(['second', 'third', 'first'])
>>> target
set(['forth', 'first'])
>>> merged = source | target
>>> merged
set(['second', 'forth', 'third', 'first'])
>>> add = source + target
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'set' and 'set'
>>>