美文网首页
字典、集合,你真的了解吗?

字典、集合,你真的了解吗?

作者: 倔强的潇洒小姐 | 来源:发表于2019-05-25 21:13 被阅读0次

    一、字典和集合基础

    字典:一系列无序元素的组合,其长度大小可变,元素可以任意地删减和改变

    优点:特别是对于查找、添加和删除操作,字典都能在常数时间复杂度内完成

    注:这里的元素,是一对键(key)和值(value)的配对


    集合:没有键和值的配对,是一系列无序的、唯一的元素组合

    注:不支持索引操作,因为集合本质上是一个哈希表,和列表不一样

    集合的 pop() 操作是删除集合中最后一个元素,可是集合本身是无序的,你无法知道会删除哪个元素,因此这个操作得谨慎使用

    >>> s = {1, 2, 4, 5, 6, 7, 8}
    >>> s.pop()
    1
    >>> s
    {2, 4, 5, 6, 7, 8}
    >>> s.pop()
    2
    >>> s.add(2)
    >>> s
    {2, 4, 5, 6, 7, 8}
    >>> s.pop()
    4
    

    补充:字典和集合,无论是键还是值,都可以是混合类型

    s = {1, 'hello', 5.0}
    

    二、字典与集合的性能

    集合是高度优化的哈希表,里面元素不能重复,并且其添加和查找操作只需 O(1) 的复杂度,那么,总的时间复杂度就只有 O(n)

    import time
    
    
    id = [x for x in range(0, 10000)]
    price = [x for x in range(10000, 20000)]
    product_test = list(zip(id, price))
    
    
    def find_unique_price_using_list(products):
        unique_price_list = []
        for _, price in products:
            if price not in unique_price_list:
                unique_price_list.append(price)
        return len(unique_price_list)
    
    
    def find_unique_price_using_set(products):
        unique_price_set = set()
        for _, price in products:
            if price not in unique_price_set:
                unique_price_set.add(price)
        return len(unique_price_set)
    
        
    start_using_list = time.perf_counter()
    find_unique_price_using_list(product_test)
    end_using_list = time.perf_counter()
    
    print('time using A: {}'.format(end_using_list-start_using_list))
    
    start_using_set = time.perf_counter()
    find_unique_price_using_set(product_test)
    end_using_set = time.perf_counter()
    
    print('time using B : {}'.format(end_using_set - start_using_set))
    

    时间输出:

    time using A: 0.538301896
    time using B : 0.0012807300000000632
    

    总结:仅仅十万的数据量,两者的速度差异就如此之大。事实上,大型企业的后台数据往往有上亿乃至十亿数量级,如果使用了不合适的数据结构,就很容易造成服务器的崩溃,不但影响用户体验,并且会给公司带来巨大的财产损失

    补充知识:
    zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

    如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

    >>>a = [1,2,3]
    >>> b = [4,5,6]
    >>> c = [4,5,6,7,8]
    >>> zipped = zip(a,b)     # 打包为元组的列表
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(a,c)              # 元素个数与最短的列表一致
    [(1, 4), (2, 5), (3, 6)]
    >>> zip(*zipped)          # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
    [(1, 2, 3), (4, 5, 6)]
    

    三、字典和集合的工作原理

    字典和集合的内部结构都是一张哈希表。

    字典:这张表存储了哈希值(hash)、键和值这 3个元素

    集合:哈希表内没有键和值的配对,只有单一的元素

    四、思考题

    1、下面初始化字典的方式,哪一种更高效?
    # Option A
    d = {'name': 'jason', 'age': 20, 'gender': 'male'}
    
    # Option B
    d = dict({'name': 'jason', 'age': 20, 'gender': 'male'})
    

    解答:OptionA 效率更高 ,因为OptionB调用dict函数等于运行时又增加了一层额外的操作,会去直接调用底层C写好的代码

    2、字典的键可以是一个列表吗?下面这段代码中,字典的初始化是否正确呢?原因是什么
    d = {'name': 'jason', ['education']: ['Tsinghua University', 'Stanford University']}
    

    解答:列表是一个动态变化的数据结构,可变类型不可hash,字典当中的 key 要求是不可变的,原因也很好理解,key 首先是不重复的,如果 Key 是可以变化的话,那么随着 Key 的变化,这里就有可能就会有重复的 Key,那么这就和字典的定义相违背;如果把这里的列表换成之前我们讲过的元组是可以的,因为元组不可变

    相关文章

      网友评论

          本文标题:字典、集合,你真的了解吗?

          本文链接:https://www.haomeiwen.com/subject/boqnaqtx.html