这基本上与文档在其另请参阅:最后部分中提到的SortedCollection
配方所做的相同,但与配方中的方法不同,显示的功能支持键功能。bisect
insert()
正在做的是与排序keys
列表并行维护一个单独的排序data
列表以提高性能(它比在每次插入之前创建键列表更快,但保留它并更新它不是严格要求的)。ActiveState 配方为您将其封装在一个类中,但在下面的代码中,它们只是传递的两个独立的独立列表(因此它们不同步会比它们都被保存更容易在配方类的一个实例中)。
from bisect import bisect_left
def insert(seq, keys, item, keyfunc=lambda v: v):
"""Insert an item into a sorted list using a separate corresponding
sorted keys list and a keyfunc() to extract the key from each item.
Based on insert() method in SortedCollection recipe:
http://code.activestate.com/recipes/577197-sortedcollection/
"""
k = keyfunc(item) # Get key.
i = bisect_left(keys, k) # Determine where to insert item.
keys.insert(i, k) # Insert key of item to keys list.
seq.insert(i, item) # Insert the item itself in the corresponding place.
# Initialize the sorted data and keys lists.
data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
data.sort(key=lambda r: r[1]) # Sort data by key value
keys = [r[1] for r in data] # Initialize keys list
print(data) # -> [('black', 0), ('blue', 1), ('red', 5), ('yellow', 8)]
insert(data, keys, ('brown', 7), keyfunc=lambda x: x[1])
print(data) # -> [('black', 0), ('blue', 1), ('red', 5), ('brown', 7), ('yellow', 8)]
追问:
可以bisect.insort_left
用吗?
不,您不能简单地使用该bisect.insort_left()
函数来执行此操作,因为它不是以支持键功能的方式编写的——相反,它只是将传递给它的整个项目与 insert, x
, 中的整个项目之一进行比较声明中的数组if a[mid] < x:
。你可以通过查看bisect
模块的源代码来了解我的意思Lib/bisect.py
。
以下是相关摘录:
def insort_left(a, x, lo=0, hi=None):
"""Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the left of the leftmost x.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if a[mid] < x: lo = mid+1
else: hi = mid
a.insert(lo, x)
您可以修改上述内容以接受可选的 key-function 参数并使用它:
def my_insort_left(a, x, lo=0, hi=None, keyfunc=lambda v: v):
x_key = keyfunc(x) # Get comparison value.
. . .
if keyfunc(a[mid]) < x_key: # Compare key values.
lo = mid+1
. . .
...并这样称呼它:
my_insort_left(data, ('brown', 7), keyfunc=lambda v: v[1])
实际上,如果您要编写自定义函数,为了提高效率而牺牲不必要的通用性,您可以省去添加通用键函数参数,只需硬编码所有内容以使用数据所需的方式进行操作你有的格式。这将避免在执行插入时重复调用键函数的开销。
def my_insort_left(a, x, lo=0, hi=None):
x_key = x[1] # Key on second element of each item in sequence.
. . .
if a[mid][1] < x_key: lo = mid+1 # Compare second element to key.
. . .
...在不传递 keyfunc 的情况下以这种方式调用:
my_insort_left(data, ('brown', 7))