class OrderBy(object):

    def __init__(self, sequence, *condition, **extra_condition):
"""
排序初始化条件
condition为优先排序条件,序列内元素必须为字典类型
extra_condition为额外的条件因素,当condition不存在时,额外条件才会生效
:param sequence:
:param condition:
:param extra_condition:
"""
self.array = sequence
self.condition = list(condition)
self.extra_condition = extra_condition
self.has_condition = bool(self.condition) def partition(self, left, right, key=None, desc=False, func=None):
"""
将区间数据进行排序
分区比较,选择一个基准,根据排序规则,正序:比基准大的放右边,比基准小的放左边
:param left: 序列区间的开始位置
:param right: 序列区间的结束位置
:param key: 对于字典对象,如果指定key,则以key对象比较否则当None值处理
:param desc: 比较规则为正序或倒序
:param func: 对值进行处理特殊处理的函数
:return:
"""
pivot = self.array[left]
if isinstance(pivot, dict):
if key is not None:
pivot = pivot.get(key)
if callable(func):
pivot = func(pivot)
low = left
while low < right:
while low < right:
_left = self.array[low]
_right = self.array[right]
if isinstance(_left, dict):
_left = _left.get(key)
if isinstance(_right, dict):
_right = _right.get(key)
if callable(func):
_left = func(_left)
_right = func(_right)
if desc:
# 倒序,右边值与基准值都不为空,且右边值小于基准值,左移
if _right and pivot and _right < pivot:
right -= 1
# 倒序,右边值为空,左移
elif not _right:
right -= 1
# 倒序,左边值与基准值都不为空,且左边值大于等于基准值,右移
elif _left and pivot and _left >= pivot:
low += 1
# 倒序,基准值为空,左边值不为空,右移
elif _left and not pivot:
low += 1
else:
break
else:
# 正序,基准为空,右边值不为空,左移
if _right and not pivot:
right -= 1
# 正序,右边值与基准都不为空,且右边值大于基准值,左移
elif _right and pivot and _right > pivot:
right -= 1
# 正序,左边值与基准都不为空,且左边值小于等于基准值,右移
elif _left and pivot and _left <= pivot:
low += 1
# 正序,左边值为空,右移
elif not _left:
low += 1
else:
break
if low < right:
temp = self.array[low]
self.array[low] = self.array[right]
self.array[right] = temp
self.array[left], self.array[low] = self.array[low], self.array[left]
return low def quick_sort(self, left=0, right=None, key=None, desc=False, func=None):
"""
快速排序算法
:param left: 区间起始位置
:param right: 区间结束位置
:param key: 字典元素使用指定键名值排序
:param desc: 是否倒序
:param func: 对于排序值,支持使用函数处理
:return:
"""
if right is None:
right = len(self.array) - 1
if left < right:
pivot_position = self.partition(left, right, key, desc, func)
self.quick_sort(left, pivot_position - 1, key, desc, func)
self.quick_sort(pivot_position + 1, right, key, desc, func) def sort(self, **condition):
if self.has_condition:
if not self.condition:
return
_condition = self.condition.pop(0)
if isinstance(_condition, dict):
condition['key'] = _condition.get('key')
condition['desc'] = _condition.get('desc', False)
else:
condition.update(**self.extra_condition)
left = condition.get('left')
right = condition.get('right')
if not left:
left = 0
condition['left'] = left
if not right:
right = len(self.array) - 1
condition['right'] = right
self.quick_sort(**condition)
self.sub_sort(left, right, condition.get('key')) def sub_sort(self, left, right, key=None, next_index=0):
"""
标记当前位置begin,及下一个位置end
当begin位置的元素与end位置元素不等时,当begin!=end - 1时,则进行区间排序
:param left: 区间起始位置
:param right: 区间结束位置
:param key: 当前排序键名
:param next_index: 下一个条件位置
:return:
"""
condition_size = len(self.condition)
if not condition_size > next_index:
return
begin = left
for end in range(left, right + 1):
_left = self.array[begin]
_right = self.array[end]
if isinstance(_left, dict):
_left = _left.get(key)
if isinstance(_right, dict):
_right = _right.get(key)
# 当上一个值与当前值不相等,则进入二次排序
# 当上一个值与当前值相等,且当前位置等于边界位置,且还有下一个排序条件,则进入二次排序
if _left != _right or (
end == right and condition_size >= next_index + 1):
condition = self.condition[next_index]
_key = condition.get('key')
desc = condition.get('desc')
func = condition.get('func')
if end == right:
_end = end
else:
_end = end - 1
self.quick_sort(begin, _end, _key, desc, func)
self.sub_sort(begin, end, _key, next_index + 1)
begin = end if __name__ == '__main__':
a = [dict(age=18, money=200, name='z1'),
dict(age=16, money=200, name='z2'),
dict(age=16, money=200, name='z3'),
dict(age=16, money=100, name='z4'),
dict(age=16, money=200, name='z5')]
order_by = OrderBy(a, dict(key='age', desc=False),
dict(key='money', desc=True),
dict(key='name', desc=True))
print(a)
order_by.sort()
print(a)

快排实现仿order by多字段排序的更多相关文章

  1. STL函数库的应用第二弹——快排sort函数与结构体关键字排序

    时隔20多天,本蒟蒻终于记起了他的博客园密码!!! 废话不多说,今天主题:STL快排函数sort()与结构体关键字排序 Part 1:引入和导语 首先,我们需要知道,algorithm库里有一些奇怪的 ...

  2. Mysql order by 多字段排序

    mysql单个字段降序排序: select * from table order by id desc; mysql单个字段升序排序: select * from table order by id ...

  3. mysql查询order by 指定字段排序

    当MySQL查询时排序的字段不是数字时而是汉字的时候也可以用when  then 来指定排序. 列如yewu_check表的status 字段不是0,1,2而是汉字待办,已办,退回.可以如下写法: S ...

  4. Quick Sort(快排)

    这是挖坑填补法的演示 快排之挖坑填补法: void Quick(int top/*起始位置*/,int end/*末尾位置*/,int arr[])//挖坑填补法 { int i=top,j=end, ...

  5. 冒泡,快排算法之javascript初体验

    引子:javascript实际使用的排序算法在标准中没有定义,可能是冒泡或快排.不用数组原生的 sort() 方法来实现冒泡和快排. Part 1:冒泡排序(Bubble Sort) 原理:临近的两数 ...

  6. 排序 之 快排、归并、插入 - <时间复杂度>----掌握思想和过程

    俗话说:天下武功无坚不破,唯快不破.对于算法当然也是要使用时间最短.占用空间最小的算法来实现了. 注意:我代码里面打的备注仅供参考,建议不要背模板(因为没有固定的模板),可以写一个数列按着代码跑两圈或 ...

  7. Java排序算法分析与实现:快排、冒泡排序、选择排序、插入排序、归并排序(二)

    一.概述: 上篇博客介绍了常见简单算法:冒泡排序.选择排序和插入排序.本文介绍高级排序算法:快速排序和归并排序.在开始介绍算法之前,首先介绍高级算法所需要的基础知识:划分.递归,并顺带介绍二分查找算法 ...

  8. Oracle 以某字段分组,以某字段排序,取前几条

    select * from (select row_number() over(partition by 以此字段为分组  order by 以此字段排序 desc rn from dual) whe ...

  9. mysql order by 多个字段排序

    工作中需用到order by 后两个字段排序,但结果却产生了一个Bug,以此备录. [1]复现问题场景 为了说明问题,模拟示例数据库表students,效果同实例. 如下语句Sql_1: SELECT ...

随机推荐

  1. 获取电脑系统唯一GUID

    软件使用微软系统的唯一ID绑定指定电脑 class Program { static void Main(string[] args) { string sysId = ""; P ...

  2. JAVA进阶15

    间歇性混吃等死,持续性踌躇满志系列-------------第15天 1.TCP网络程序 package code0329; import java.io.BufferedReader; import ...

  3. Apple Tree POJ - 2486 (树形dp)

    题目链接: D - 树形dp  POJ - 2486 题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 学习网址:https://blog.c ...

  4. 2018-2019-2 网络对抗技术 20165237 Exp6 信息搜集与漏洞扫描

    2018-2019-2 网络对抗技术 20165237 Exp6 信息搜集与漏洞扫描 实验目标 1 各种搜索技巧的应用: 2 DNS IP注册信息的查询: 3 基本的扫描技术: 主机发现.端口扫描.O ...

  5. 2018-2019-2 20165325 《网络对抗技术》 Exp5:MSF基础应用

    2018-2019-2 20165325 <网络对抗技术> Exp5:MSF基础应用 实验内容(概要) 1.1 一个主动攻击实践,本实验选择 ms17_010_eternalblue(成功 ...

  6. 【干货】使用SIFT取证工作站校验文件哈希----哈希一致则文件具备完整性

    此实验来源于课程活动部分:第1单元:计算机取证基础  1.3活动和讨论  活动:* nix系统中文件的基本散列 注意:本博客更多的信息可能没有交代完善,有的人看不明白是因为,我知道,但是没有写出来.本 ...

  7. Shell-仅保留最近3天的备份文件: find . -name "*.sql" -mtime +3 -ls -exec rm {} \;

    Code: find . -name "*.sql" -mtime +3 -ls -exec rm {} \;

  8. Django-CSRF,AJAX,FORM

    内容总览1.CSRF相关1>CSRF源码分析2>ajax的实现(ajax的实例(异步计算,参数测试,上传))3>ajax通过csrf的校验 2.FORM组件1>基本使用2> ...

  9. C#使用RabbitMQ(转)

      1. 说明 在企业应用系统领域,会面对不同系统之间的通信.集成与整合,尤其当面临异构系统时,这种分布式的调用与通信变得越发重要.其次,系统中一般会有很多对实时性要求不高的但是执行起来比较较耗时的地 ...

  10. Gitlab_ansible_jenkins三剑客②Gitlab的后台管理

    系统信息和日志 健康状态 使用gitlab的用户管理和审批功能 创建用户 创建一个lead普通账号 进入test-repo仓库 这样就把dev添加到了test-repo这个项目中,并且有了develo ...