Python中的去重问题,这或许是个简单的问题。
比如一个list:a = [1,3,2,9,5,3,1,5],如何删除重复元素,嗯,有一个高端的方法:
#方法一
a = set(a)
a:1, 2, 3, 5, 9.哇,好高端,事情可没这么简单,观察,a的顺序变的,类型也变了
print a,type(a)
set([1, 2, 3, 5, 9])
a变成了python里面的集合类型,顺序且无重复元素,跟sort的功能有点类似,好用,但是这个上述方法既改变的a的类型又改变了a中元素既有顺序(虽然用类型转换成将a变为list类型。
注意a里面的元素全是数字,如果将a里面有其它元素比如:
a = [1,3,2,9,5,3,1,5,[1,2],[1,2]]
print set(a)
TypeError: unhashable type: ‘list‘
于是发现set这个方法不好使了,原因是a里面出现了不可哈希的元素类型,那何为可哈希元素呢?
python文档里面是这么说的:
An object ishashable if it has a hash value which never changes duringits lifetime (it needs a__hash__() method), and can be compared to other objects (it needs an__eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value.
意思就是说生存期内存可变的对象不可哈希,像list,dict就是不可哈希的,因为它们是可变对象,tuple和str就是不可变对象,是可哈希的。
因此,这个问题产生的原因在于不能想当然地认为list中的元素都是可哈希的,这并不是一个通用的解决方案
#方法二
再看另一种方法,用函数。
from collections import Counter
a = [1,3,2,9,5,3,1,5]
c = Counter(a)
print c
输了结果为:
Counter({1: 2, 3: 2, 5: 2, 2: 1, 9: 1})
这不错,将a中的每个元素的个数都列举出来了,这样的话只需要根据c元素与之对应的元素个数删除重复元素即可(c的类型为Counter,可以看出跟dict类型相似,用法也是相似的)
c = {k:v-1 for k,v in c.items() if v > 1}#将a中元素个数大于1的元素找出来,v-1表示要删除的重复元素的个数
for k,v in c.items():
for i in range(v):#根据重复次数删除重复元素
a.remove(k)
如此便可达到去重的目的,貌似有点复杂哦。
看到有网友用这个方法:
a = sorted(set(a),key = a.index)
矮小精悍,很不错哦
但是这些方法同样不支持不可哈希对象的操作,因此这个方法也不具有通用性。
#方法三
那只有最笨的方法了
c = {a.count(a[i]):a[i] for i in xrange(len(a))}
然后套用方法二即可,在运用这个方法的过程中,发现dict类型为key:value的形式,其中key的值只能为可哈希元素,又引申出一个新的问题,回头再读一读陈儒写的python源码剖析,呵呵!
未完,待续……