使用Python的Bisect模块

2020-11-22 13:18:24

博客JUNTO联系人bisect模块的目标是使您能够有效地搜索和更新排序的列表。为此,它提供:

在统计数据装仓中,您有一个要分组为“箱”的数据。例如。

您具有学生成绩的数据,并且希望将80到90之间的分数分组为“ B”,将90到100之间的分数分组为“ A”,依此类推。

对我来说,一种简单的方法是编写一个计算bin的函数,例如对水果进行装箱:

def bin_fruit(fruit):如果[“ lemon”,“ orange”]中的水果:返回“ citrus” elif [[“ apple”,“ pear”]中的水果:返回“ malinae” import randomdata = random.choices([ “,” orange“,” apple“,” pear“],k = 10)data

def bin_score(分数):如果90 <=分数<= 100:返回“ A” elif 80 <=分数<90:返回“ B” elif 70 <=分数<80:返回“ C” elif 60 <=分数<70 :返回“ D” Elif得分<60:返回“ F” import randomdata = [ran_randrand(50,100)for _ in range(10)] data

对于n个记录和m个仓的数据集,此方法的时间复杂度往往是

由于对一个记录进行分箱需要O(m)的时间-选中O(m)if语句-并且需要对n个记录进行分箱。

如果箱数m为常数,则整个时间复杂度仅为O(n)。

但是,如果箱数m足够大而直接方法太慢怎么办?

bins = {“柠檬”:“柑橘”,“橙色”:“柑橘”,“苹果”:“麦莉娜”,“梨”:“麦莉娜”,} def bin_fruit(fruit):return bins [fruit] import randomdata = random.choices([“柠檬”,“橙色”,“苹果”,“梨”],k = 10)数据

这种方式对一个记录进行绑定需要O(1)时间-不管bin的数量是多少-因为字典是使用哈希表实现的。创建字典需要O(m)时间-每个bin都有一个条目。因此,对于n个记录和m个仓,总的时间复杂度为

score_bins = [60、70、80、90] score_letters = [“ F”,“ D”,“ C”,“ B”,“ A”] import bisectdef bin_score(score):i = bisect.bisect(score_bins,得分)return score_letters [i] import randomdata = [range(10)中_的[random.randint(50,100)]

用这种方式对一条记录进行绑定需要O(log m)时间,因为bisect.bisect使用二进制搜索来导航score_bins。创建score_bins需要O(m)时间。因此,对于n个记录和m个仓,总的时间复杂度为

注意:如果您能够使用第三方库(例如NumPy或Pandas),请查看以下函数:numpy.digitize,numpy.searchsorted,pandas.Series.searchsorted,pandas.qcut,pandas.cut。

例如,您可以想象有一个定期报告温度的温度传感器。您希望定期报告中间温度,并能够在到达时合并新的温度数据。

def add_new_measurement(数据,温度):data.append(温度)def中值(数据):返回统计信息。median(数据)import randomimport statisticsdata = [ran_randrand(93,100)for _ in range(10)] data

因此,如果工作负载需要频繁添加新数据并且不经常计算中位数,则此方法效果很好。

但是如果工作量倒退了怎么办?例如,如果每两分钟收到一次温度测量值,但必须每两秒钟计算一次中值。

在那种情况下,我认为我们最好通过加快计算中位数来解决问题,即使是以减慢添加新数据的代价为代价。

如果数据已经排序,则可以在O(1)时间内完成计算订单统计信息。因此,处理此工作负载的一种直接方法是在附加数据后对数据进行排序,并利用对数据进行排序的事实来有效地计算中位数:

def add_new_measurement(数据,温度):data.append(温度)data.sort()def中位数(数据):n = len(数据)如果n%2 == 0:返回(data [(n // 2)- 1] + data [n // 2])/ 2 else:返回数据[n // 2] import randomdata = sorted(random.randint(93,100)for _ in range(10))data

但是我认为使用bisect.insort可以进一步提高添加新数据的时间复杂度。

在本周的帖子中,您学习了如何使用bisect模块进行统计数据装仓并将新数据添加到已排序列表中。

像温度传感器一样,逐段处理输入的算法称为在线算法。

bisect.insort可用于实现插入排序。 Insertionsort是一种在线算法,并且与Python的内置timsort一起是一种自适应排序算法,因为它利用了部分排序的数据的优势。

如果您喜欢本周的帖子,请与您的朋友分享,并继续关注下一周的帖子。回头见!

(如果您发现此帖子有任何错误或错别字,请通过我的联系页面与我联系