python 从字典里取出内容,创建集合 dict -> set

这是《python 编程实践》这本书,第九章,最后一道题,14题。

稀疏向量(sparse vector)就是其元素几乎都为0的那种向量,比如[1,0,0,0,0,0,3,0,0,0] 如果将这些0 都保存到列表中实在是有些浪费存储内存。因此程序员常常会利用字典来保存其中的非零元素。比如说,刚才那个向量会写成{0:1, 6:3}, 这是因为, 该向量位置0处的值为1, 位置6 处的值为3.

a)编写一个叫sparse_add的函数,其参数为两个以字典为形式存储的稀疏向量,要求返回一个表示他们和的新字典。

b)编写一个名为sparse_dot的函数,其作用是计算两个稀疏向量的点积

c)你的上司要求你编写一个名为sparse_len的函数,其作用是返回一个稀疏向量的长度(就好像python中的len函数一样可以返回列表的长度那样。)纳闷,在编写该函数执勤,你还需要问他点什么呢?


好了,为了解决问题。


先上一部分铺垫内容:

1. 字典

字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必须是可哈希的。可哈希表示key必须是不可变类型,如:数字、字符串、只含不可变类型元素的元组(1,2,3,’abc’)、实现__hash__()方法的自定义对象(因为__hash__()须返回一个整数,否则会出现异常:TypeError: an integer is required)。可以用hash(obj)检测对象是否是可哈希的。

>>> class HashEnable(object):
...    def  __hash__(self):
...         return 1
>>> he = HashEnable()
>>> hash(he)
1
>>> d = {he:1}
>>> d = {['1',2]:2}
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'
list 是 mutable的,可变的,所以不能有固定的hash值,所以unhashable , 出错。首先要将数组变成tuple元组就好多了。


为什么写关于tuple的东西呢,因为在很多增加set集合元素的时候,list列表里面的元素不能被append增加上,因为list是mutable可变的。由于tuple元组是immutable不可变的,所以,我们可以用tuple(一个list),来返回一个不可变的元组,这样就能增加大set中了。


关于这个上面的习题,这里第一题a)与b)几乎是一样的,只要

分两个过程

一个是叫

decode 解码: 将 输入的dict字典转换成添上相应位置0的完整list列表。

encode 编码:将 处理完成后的新的list列表转换呈新得dict字典。


于是我们可以这样做。

"""
A program to zip and unzip codes, to describe a list, which has many "0" elements, in a dict
"""
def sparse_add(dict1, dict2):
    dict_new = {}		# the dict_new derived from dict1, dict
    list1 = []			# list1 for dict1
    list2 = []			# list2 for dict2
    summed = []			# summed for dict1 and dict2
    temp1 = dict1.items()	# a list from dict1
    temp2 = dict2.items()	# a list from dict2
    """
    Decode section
    """    
    
    for i in range(10):
        """for dict1 to be appened into list1
        """
        list1.append( dict1.get(i,0) )
        list2.append( dict2.get(i,0) )
        
        """
        这里是由于没有使用dict1.get(i,0)的形式的尝试,非常笨拙,效率很低,而且错误。得出的结论就是,多多使用意境写好的方法
        """
        #if i < len(temp1):
            
            #if temp1[i][0]:		#if it exists, then it be appended to list1
                #list1.append(temp1[i][1])
            #else:
                #list1.append(0)		# if not exists, just append 0
        #else:
            #list1.append(0)		# if not exists, 
            
        #"""for dict2 to be appened into list2
        #"""        
        #if i < len(temp2):
            
            #if temp2[i][0]:
                #list2.append(temp2[i][1])
            #else:
                #list2.append(0)
        #else:
            #list2.append(0)
        summed.append((list1[i] + list2[i]))
    
    """
    Encode section
    """
    for i in range(len(summed)):
        if summed[i] != 0 :		# if not 0, then be in dict_new
            temp = {i:summed[i]}
            dict_new.update(temp)
    print dict_new


这样当你输入

import sparse_add_out
dict1 = {0:3,5:2,6:10}
dict2 = {0:4,4:11,9:1}

的时候,

sparse_add_out.sparse_add(dict1,dict2)
{0: 7, 9: 1, 4: 11, 5: 2, 6: 10}

得到的结果是你想要的。由于dict里面是不分排序的所以,排列顺序不是从0到9的。这主要是由于hash的缘故。hash将不同的值能换算成一串数字,根据这个数字进行排序。而且是唯一的,不可以变的,所以,在set与dict里面,比较容易查找相关的数据,而不是一遍又一遍地搜索了。

后面的b)与c)就很简单了,简单的修改一下上面的代码就好了。 不超过20行就能完成。


你可能感兴趣的:(python)