Python中的序列类型(二)

list.sort 方法和内置的 sorted 函数

list.sort

list 定义了一个排序方法 list.sort
,这个方法会就地排序列表,而不会将原列表复制排序生成新的列表。这也是其返回值为 None的原因,提示你这个方法不会新建列表

Python 风格:一个函数或方法对对象就地进行改动,其返回值为 None,好让调用者知道传入参数发生了变化。

从 python3.4 开始删除了 list.sort 方法,只能使用 sorted 创建一个新的有序序列

内置 sorted函数:

用法:sorted(iterable)

接受任何可迭代对象,其与 list.sort 不同,会将原对象复制一份,对复制进行排序,返回这个排序后的复制内容。

list.sortsorted 函数均可接受两个关键字参数:reverse 和 key

reverse:默认值为False,即升序排列,如果设置为 True,则按照降序排列

key: 传入的是func,以该 func 作用在对象元素后的值作为排序依据进行排序,但不改变对象元素。

>>> l = ['a', 'C', 'm', 'd', 'B']
>>> l.sort(key=lambda x: x.lower(), reverse=True)
>>> l
['m', 'd', 'C', 'B', 'a']

list.sortsorted 背后的排序算法是 Timsort,他是稳定的,何为稳定,看下面例子:

>>> fruits=['grape', 'raspberry', 'apple', 'banana']
>>> sorted(fruits, key=len)
['grape', 'apple', 'banana', 'raspberry']
>>> sorted(fruits, key=len, reverse=True)
['raspberry', 'banana', 'grape', 'apple']

排序方法相反,一顺一逆,为何结果并不完全相反,这就是排序稳定,当两个元素比不出大小,他们的相对位置是固定的,与原来列表相同。

bisect

bisect 模块有两个主要函数 bisect 和 insort,两者都利用二分查找算法在有序序列查找和插入元素。

bisect(haystack, needle) 函数在干草垛(haystack)里搜索针(needle)的位置,该位置满足的条件是:将 needle 插入这个位置后,haystack 还能保持升序,也就是这个函数返回的位置前面的值,都小于或等于 needle 的值,haystack 必须有序。

可以先用 bisect(haystack, needle) 查找位置index,之后用 haystack.insert(index, needle) 插入新值。也可以使用 insort 来一步到位

def ch2_17():
    """
    在haystack中打印出每个needle应属的位置
    """

    haystack = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
    needles = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]

    row_fom = '{0:2d} @ {1:2d}     {2}{0:<2d}'

    def demo(bisect_fn):
        for needle in reversed(needles):
            position = bisect_fn(haystack, needle)
            offset ='  |' * position
            print(row_fom.format(needle, position, offset))

    if sys.argv[-1] == 'left':
        bisect_fn = bisect.bisect_left
    else:
        bisect_fn = bisect.bisect
    print('DEMO: ', bisect_fn.__name__)
    print('haystack -> ', ' '.join('%2d' % n for n in haystack))
    demo(bisect_fn)
DEMO:  bisect
haystack ->   1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14       |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 14       |  |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 13       |  |  |  |  |  |  |  |  |  |  |  |  |29
23 @ 11       |  |  |  |  |  |  |  |  |  |  |23
22 @  9       |  |  |  |  |  |  |  |  |22
10 @  5       |  |  |  |  |10
 8 @  5       |  |  |  |  |8 
 5 @  3       |  |  |5 
 2 @  1       |2 
 1 @  1       |1 
 0 @  0     0 

也可以利用 bisect 建立索引,比如将分数和等级对应起来:

def grade(score, scores = [60, 70, 80, 90], ranks = 'FDCBA'):
    i = bisect.bisect(scores, score)
    return ranks[i]

l = [random.randint(50, 100) for x in range(10)]
print(l)
print(list(map(grade, l)))
[91, 55, 87, 66, 55, 86, 93, 61, 100, 68]
['A', 'F', 'B', 'D', 'F', 'B', 'A', 'D', 'A', 'D']

数组

列表很灵活简单,但在某些情况下其不是最好选择,比如当我要存储一百万个随机浮点数时,数组(array)会是更好的选择,因为数组背后存的并不是浮 float 对象,而是数字的机器翻译,也就是字节表示。

数组支持列表的所有跟可变序列有关的操作:pop、extend、insert,也支持存入文件 tofile 和从文件读取 fromfile

from array import array
from random import random

floats = array('d', [random() for x in range(10**7)])
with open('floats.bin', 'wb') as fp:
    floats.tofile(fp)

floats2 = array('d')
with open('floats.bin', 'rb') as fp:
    floats2.fromfile(fp)

内存视图

numpy

deque

当我们在对表使用 pop(index) 删除其前面的元素时, 被删除元素的后面所有元素均要移动,所以会很耗时。

这时可以使用 deque 双向队列,其具有:

  • 线程安全

  • 可以快速从两端添加或删除元素

  • 创建 deque 对象时可以指定对象长度,这样当队列满员时向首尾添加元素,会删除过期的部分

>>> from collections import deque
>>> dq = deque(range(10), maxlen = 10)
>>> dq
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.rotate(3)
>>> dq
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
>>> dq.rotate(-4)
>>> dq
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
>>> dq.extend([10, 20, 30, 40])
>>> dq
deque([5, 6, 7, 8, 9, 0, 10, 20, 30, 40], maxlen=10)
>>> dq.extendleft([50, 60])
>>> dq
deque([60, 50, 5, 6, 7, 8, 9, 0, 10, 20], maxlen=10)

如上,deque 支持 rotate(steps) 方法,当 steps > 0 时,序列中所有元素会向右移动 steps 位,最右边 steps 个元素将出现在序列左边,steps < 0 时相反。

下图是 list 与 deque 的方法对比:

[图片上传失败...(image-cab70f-1544191699167)]

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容

  • 注:本文摘自《流畅的Python》一书,目的是为了个人学习使用 1.容器类型 这些序列能存放不同类型的数据。容器序...
    第八共同体阅读 892评论 0 0
  • python序列类型 容器序列 容器序列能够存放不同类型的数据,像list、tuple和collections.d...
    若无若虚阅读 359评论 0 0
  • 姓名:袁明辉 公司:宁波惠尔顿婴童安全科技股份有限公司 组别:利他一组 【知~学习】 背诵《六项精进大纲》3遍 背...
    YuanWelldon阅读 80评论 0 0
  • 我是睡不醒的瞌睡虫,昨天疲惫的回到家,早早就睡了,很快入了梦乡,至于中间就早上去了趟厕所,接着又继续睡。小风扇一直...
    平凡山丘阅读 208评论 0 0
  • 没有反思的人生,不值得过---苏格拉底 我是一切的根源,所有的发生都是来成就我的。 一、【身体与健康】 早起(5:...
    捉不住的呼吸阅读 104评论 0 0