百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

多种结构难以选择老手告诉你,适合场景的才是最好的(下篇)

toyiye 2024-06-21 12:02 9 浏览 0 评论

上一篇中介绍的四种结构相信大家已经看了,剩下的部分我会举例介绍这6种结构及各自的使用场景。

5.deque

deque双端队列,基于list优化了列表两端的增删数据操作。举个例子:

from collections import deque 
 
In [3]: d = deque([3,2,4,0])                                                     
 
In [4]: d.popleft() # 左侧移除元素,O(1)时间复杂度                                                             
Out[4]: 3 
 
In [5]: d.appendleft(3) # 左侧添加元素,O(1)时间复杂度                                                        
 
In [6]: d                                                                        
Out[6]: deque([3, 2, 4, 0]) 

适合场景:list左边添加删除的元素时间复杂度都为O(n),所以如果是模拟队列的情况情况下比较忌讳使用list,这时候deque的作用就被凸显出来了,它非常适合列表两端的大量操作。有一点需要注意,加强版的deque牺牲掉了空间的复杂程度所以嵌套deque就要仔细trade-off:

In [9]: sys.getsizeof(deque())                                                   
Out[9]: 640 
 
In [10]: sys.getsizeof(list())                                                   
Out[10]: 72 

其本质在python通过使用长度默认为64的数组来实现deque,从左边删除1个元素的时候,leftindex加1,如果超过64就会释放原来的内存块,重新申请64长度的数组,然后再用block对内存部分进行管理。

6.counter

这个是用来统计元素个数的数据结构,也可以称之为bag或multiset。

from collections import Counter 
In [14]: c = Counter([1,3,2,3,4,2,2]) # 统计每个元素的出现次数 
In [17]: c                                                                       
Out[17]: Counter({1: 1, 3: 2, 2: 3, 4: 1}) 
 
# 除此之外,还可以统计最常见的项 
# 如统计第1最常见的项,返回元素及其次数的元组 
In [16]: c.most_common(1)                                                        
Out[16]: [(2, 3)] 

如果你发现这个场景可以用dict处理,那就用dict处理,最好不要用counter,因为counter可以说是dict的衍生版,但是如果统计元素出现频次,这个时候果断选择counter即可。在这里特别提醒一下,Counter统计的元素要求可哈希,这是什么意思呢?意思就是如果统计list的出现次数是不可行的,但是如果将list转化tuple则哈希就是被允许的了。所以总结一下就是Counter实现基于dict,它将元素存储于keys上,出现次数为values。

7.OrderedDict

它也是继承于dict,其作用是能保证keys数值可以按照既定的顺序取出。

In [25]: from collections import OrderedDict                                     
 
In [26]: od = OrderedDict({'c':3,'a':1,'b':2})                                   
 
In [27]: for k,v in od.items():  
    ...:     print(k,v)  
    ...:                                                                         
c 3 
a 1 
b 2 

如果只使用dict没办法保证顺序,keys映射为哈希数值,但是这个数值在散列表中的储存顺序是乱的,所以需要在保证keys有序,就需要选择OrderdDict。这个的本质看cpython里面对一个双向链表self.__root是一直维护的,为什么呢?说直接一点,就是维护着key的顺序。既然提到双向的链表,那么问题就来了,删除键值对如何保证O(1)时间完成?

cpython使用空间换取时间的做法,它内部是存在着一个elf.__map字典去维护的,这个建为key值为指向双向链表节点的link. 这样在删除某个键值对时,通过__map在O(1)内找到link,然后O(1)内从双向链表__root中摘除。

8.heapq

以list作为基础进而优化的数据结构,我们通常叫做堆队列,也称之为优先队列。它的特点是最小元素总是在根节点。

import heapq 
In [41]: a = [3,1,4,5,2,1]                                                       
 
In [42]: heapq.heapify(a) # 对a建堆,建堆后完成对a的就地排序 
In [43]: a[0] # a[0]一定是最小元素 
In [44]: a 
Out[44]: [1, 1, 3, 5, 2, 4] 
 
In [46]: heapq.nlargest(3,a) # a的前3个最大元素                                                     
Out[46]: [5, 4, 3] 
 
In [47]: heapq.nsmallest(3,a) # a的前3个最小元素                                                   
Out[47]: [1, 1, 2] 

如果在这个场景中我们需要统计list中几个最大或是最小的几个元素,这个时候使用heapq就是好时机了,不仅如此,它还可以将多个有序小list合并为大list。其原理是堆是一个二叉树,其父节点的值只会大于或者小于其子节点的值,原理和堆排序是非常类似的。

9.defaultdict

defaultdict可以说是一个自带默认工厂的dict,工厂的全称是对象工厂。

基本dict键的值没有一个默认数据类型,如果值为list,必须要手动创建:

words=['book','nice','great','book'] 
d = {} 
for i,word in enumerate(words): 
    if word in d: 
        d[word].append(i) 
    else: 
        d[word]=[i] # 显示的创建一个list 

但是如果使用defaultdict:

from collections import defaultdict 
d = defaultdict(list) # 创建字典值默认为list的字典 
for i,word in enumerate(words): 
    d[word] = i  

当我们省略if逻辑判断,这个时候代码就清晰了一瞬间。上面defaultdict(list)这行代码的默认创建数值为list的字典,这还可以构造defaultdict(set), defaultdict(dict)等等,这就是对象工厂可以做到的内容。根据前文说的这些所有内容可以推断出,适用于键的值必须要有一个有默认值的场景。其原理在于调用工厂函数来对确实键的值进行提供。

10.ChainMap

在使用ChainMap的前提是假设你需要将多个dict来合并成一个大的dict,在这样的条件下,ChainMap就是你的最优解,其同步更改的特性会让你方便很多很多。举个例子:

In [55]: from collections import ChainMap                                        
 
In [56]: d1 = {'a':1,'c':3,'b':2}                                                
 
In [57]: d2 = {'d':1,'e':5}                                                      
 
In [58]: dm = ChainMap(d1,d2)                                                    
 
In [59]: dm                                                                      
Out[59]: ChainMap({'a': 1, 'c': 3, 'b': 2}, {'d': 1, 'e': 5}) 

ChainMap后返回一个大dict视图,如果修改其对应键值对,原小dict也会改变:

In [86]: dm.maps  # 返回一个字典list                                                                
Out[86]: [{'a': 2, 'c': 3, 'b': 2, 'd': 10}, {'d': 1, 'e': 5}] 
 
In [87]: dm.maps[0]['d']=20   # 修改第一个dict的键等于'd'的值为20                                                    
 
In [88]: dm                                                                      
Out[88]: ChainMap({'a': 2, 'c': 3, 'b': 2, 'd': 20}, {'d': 1, 'e': 5}) 
 
In [89]: d1 # 原小dict的键值变为20                                                                     
Out[89]: {'a': 2, 'c': 3, 'b': 2, 'd': 20} 

在选择ChainMap的时候是这个场景需要我们有多个字典或者映射,想集合成为一个单独的映射。有经验的人可以说是通过update来进行合并,但是这样会导致建立了一个新的内存结构,不仅浪费空间,而且对新字典更改时不会与原字典同步。

通过两篇文章已经介绍了4种基本的常用结构,6种基于它们进而优化的特定结构。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码