• 二.再次了解字典和集合


    我们在第一章对列表和元组深入的了解了一下,这次我们来看看另外两种常用的数据类型:字典(dict)和集合(set) 。

    一.基础知识:

      字典是一系列由键(key)和值(value)配对组成的元素的集合,只有在3.7以后的版本中字典才被确定为有序的。其长度可变,元素可以任意增减和改变。

      集合和字典基本相同,区别就是没有键值的配对,并且是一系列无序的、唯一的元素的集合。

      相比于列表和元组,字典的性能更优,特别是对于查找、添加和删除操作,字典都能在常数时间复杂度内完成操作。

    二.使用

      假设我们由下面几个字典和集合

    dic = {'1':"a",
           '2':'b',
           3:'c'}
    s = {1,'abc',3.0}

      可以发现,不论是字典还是集合无论是键还是值,数据类型都可以是混合使用的。

      而对于元素访问的问题,字典可以直通过对引键的值来进行索引,如果键不存在,就会抛出异常。

    dic[1]
    Traceback (most recent call last):
      File "D:/python/happy chicken/123.py", line 5, in <module>
        dic[1]
    KeyError: 1

      如果是直接这样索引键的值,一定要加上容错的机制,否则程序就崩溃了。还有一种方法是用get()函数,如果键不存在就会返回一个None。

    dic.get(1)
    'None'

      而集合由于是无序的,不支持索引操作。因为集合本质上和列表不同,是一个哈希表。所以可以通过valve in set/dic的方式判定值是否在列表或字典里(字典只能判定key是否在)。

    '1' in dic
    1 in s
    Ture
    Ture

      当然也包括增删改查的操作

    #
    dic[4] = 'd'
    s.add('abc')
    #
    dic.pop[3]
    s.remove(1)
    s.pop()
    #
    dic['1']='aaa'

    注意的是由于集合是无序的,用pop()函数的话是随机最后一个元素,那就不知道删的是哪个了!一定要谨慎使用

    三.性能

      我们做一个这样的试验:有一个商品列表,元素是一个元组,里面存了该商品的ID(int)和单价(float),我们试一下检索这件商品的价格

    products = [(0,100.0),(1,99.5),(2,50.6),(3,47.7)]
    
    def find_product_price(products,product_id):
        for id,price in products:
            if id == product_id:
                return price
        return None
    
    price = find_product_price(products,2)
    print(price)

    假设商品列表里有n个元素,那么查找的过程要遍历整个列表,呢么时间复杂度为O(n)。即使我们先对列表排序后用二分法查找也需要O(logn)的时间复杂度。而列表的排序也要O(nlogn)的时间。

    而如果我们用字典的类型存储这些数据,那么查找就会变得很高效。只需O(1)的时间复杂度就可以完成。由于字典内部是一个哈希表,可以通过键的哈希值来找对应的值。

    products = {0:100.0,
                1:99.5,
                2:50.6,
                3:47.7}
    def find_product_price(products,product_id):
        return products.get(product_id)
    price = find_product_price(products,2)
    print(price)

    看,操作起来是不是也更简单(这里是为了比较,其实都不用这个函数,直接用get()索引id对应的价格就可以了!)

    在来一个难一点的:现在要统计一下这些商品中有多少种价格,我们试一下分别用列表和集合来实现。

    products = [(0,100.0),(1,99.5),(2,50.6),(3,47.7),(4,47.7)]
    
    def find_unique_price(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)
    
    print(find_unique_price(products))

    这里用了一层for循环嵌套了一个if判断,假设原始的列表有n个元素,最差的情况下需要O(n^2)的时间复杂度。

    products = [(0,100.0),(1,99.5),(2,50.6),(3,47.7),(4,47.7)]
    
    def find_unique_price(products):
        uniqur_price_set = set()    #创建集合
        for _,price in products:
            uniqur_price_set.add(price)
        return len(uniqur_price_set)
    
    print(find_unique_price(products))

    这里用了一个集合,每次循环直接把price加在集合里。而集合是去重的,而添加和查找的操作只需要O(1)的时间复杂度,那么总时间复杂度就只有O(n)。

    这里由于元素少不是特别直观我们直接生成一个1,000,000个元素的产品列表演示一下

    import time
    id = [x for x in range(0,1000000)]
    price = [x for x in range(20000,30000)]
    products = list(zip(id,price))
    start_time = time.perf_counter()
    find_unique_price(products)
    end_time = time.perf_counter()
    print(end_time-start_time)
    列表时间:0.6533774739276819
    集合时间:0.0012942212969428366

    可以看出了只有1000000个数巨量两者的速度就差了这么多,如果使用了不合适的数据结构很容易造成服务器的崩溃。

    四.字典和集合的工作原理

      上面说过了,字典和集合内部结构都是一个哈希表,对于字典来说,表内存了哈希值(hash),key,value三个元素;而对集合来说就只有单一的元素了。至于在哈希表内是如何存储的,我们以后有时间再分析!

  • 相关阅读:
    mysql 开启sql执行日志
    opcache.revalidate_freq 修改无效
    centos7 maven3.6.3安装
    CentOS7.5下基于FTP服务的局域网yum源搭建
    Centos7——防火墙(Firewall)开启常见端口命令
    Linux系统通过firewall限制或开放IP及端口
    CentOS7 FTP安装与配置
    centos7 搭建个人-企业私有云盘-seafile
    Centos6-7下杀毒软件clamav的安装和使用 (已成功测试)-----转发
    tomcat 安全规范(tomcat安全加固和规范1)--转发
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/11113498.html
Copyright © 2020-2023  润新知