1. 程式人生 > >流暢的Python---list排序和保持有序序列

流暢的Python---list排序和保持有序序列

nts 一個 序列 and () 關鍵參數 獲取 可選 地址

1. 列表 使用 list.sort方法 和內置函數 sorted 排序

  不管是list.sort還是sorted函數,list.sort會就地排序列表,不會把列表復制一份,sorted會產生新的對象,有兩個可選關鍵參數:reverse 和 key。

    reverse:ture為降序。默認為false,為升序。

    key:  排序算法依賴的對比關鍵字。比如:key=str.lower 實現忽略大小寫的排序 , key=len 實現字符串長度的排序,默認的是恒等函數,也就是默認使用元素的值排序。

# 水果list
fruits = [‘grape‘, ‘raspberry‘, ‘apple‘, ‘banana‘]
# 獲取對象內存地址
print(id(fruits))
# 使用list.sort默認排序
fruits.sort()
# 查看效果
print(fruits)
# 使用內置sorted函數默認排序
print(sorted(fruits))
# 獲取對象內存地址
print(id(fruits))
# 獲取對象內存地址
print(id(sorted(fruits)))

# 結果
# 1597512311304
# [‘apple‘, ‘banana‘, ‘grape‘, ‘raspberry‘]
# [‘apple‘, ‘banana‘, ‘grape‘, ‘raspberry‘]
# 1597512311304
# 1597512311368

  list.sort(key= ,reverse = ) 與sorted(list, key = , reverse = )等可選參數的排序,可自行嘗試結果。

2. 使用bisect 保持已排序列

  bisect是一個模塊,這個模塊中主要包括兩個函數:bisect 和 insort 。這兩個函數都是使用二分查找算法對有序序列中查找或插入元素。

  註意:必須是已經排好序的有序序列。

  模塊bisect中bisect函數:bisect(有序序列L,想搜索的值x),返回x可以插入L中的index,(所以說,如果是升序的情況下,返回的index前邊的值都是小於或等於x的值),index是有序序列中的索引。

             找到index後再使用L.insert(index,想搜索的值x)插入新值x。

  我們也可以使用模塊bisect中insort函數一步到位。

# 引入bisect模塊
import bisect
# import sys

# 制作一有序序列 HAYSTACK
HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
# 想要插入HAYSTACK中的值
NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]
# 打印輸出,format用法 ,2d補足寬度為2
ROW_FMT = ‘{0:2d} @ {1:2d}    {2}{0:<2d}‘
# 寫一個demo函數打印效果
def demo(bisect_fn):
    # 將需要插入的數 一個一個的遍歷
    for needle in reversed(NEEDLES):
        # 返回可插入的位置
        position = bisect_fn(HAYSTACK, needle)
        # 位置數從1開始,所以打印將前方的數都置為 |
        offset = position * ‘  |‘
        # 填充數據
        print(ROW_FMT.format(needle, position, offset))

if __name__ == ‘__main__‘:
    bisect_fn = bisect.bisect
    print(‘DEMO:‘, bisect_fn.__name__)
    print(‘haystack ->‘, ‘ ‘.join(‘%2d‘ % n for n in HAYSTACK))
    demo(bisect_fn) 

# 結果
# DEMO: bisect_right
# 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中兩個可選參數:lo和hi 縮小收縮範圍

  這種使用方式在很多地方都使用的上,例如:一個人的各科成績要轉換成對應的 成績 等級,4行代碼解決問題

def grade(score,breakpoints=[60, 70, 80, 90],grades=‘FDCBA‘):
    i = bisect.bisect(breakpoints, score)
    return grades[i]
print([grade(score) for score in [33, 99 ,77 ,70 , 89, 90, 100]])
# 結果
# [‘F‘, ‘A‘, ‘C‘, ‘C‘, ‘B‘, ‘A‘, ‘A‘]

  用bisect.insort插入新元素

import bisect
import random

SIZE = 7
# seed改變隨機數生成器的種子,使每次結果相同
random.seed(1729)
my_list = []
for i in range(SIZE):
    # 0到SIZE*2選取一個隨機數
    new_item = random.randrange(SIZE*2)
    bisect.insort(my_list, new_item)
    print(‘%2d ->‘ % new_item,my_list)
# 結果    
# 10 -> [10]
#  0 -> [0, 10]
#  6 -> [0, 6, 10]
#  8 -> [0, 6, 8, 10]
#  7 -> [0, 6, 7, 8, 10]
#  2 -> [0, 2, 6, 7, 8, 10]
# 10 -> [0, 2, 6, 7, 8, 10, 10]

 

  

流暢的Python---list排序和保持有序序列