#Lua_table.sort多条件(大量条件)自定义排序
之前简单写了(实际上大部分都是别人的链接)一些关于table.sortde的简单使用,采坑地点,常见使用等,这次就最近项目中的一个需求来记录一下。
##table.sort小记
1.排序的原理(快速排序)
2.排序顺序的依据(return a < b 看返回结果的判断 这个结果是小于)
3.排序的坑点(==的情况一定要返回false)
备注:如果需要自定义comp函数,copm(a,b) 如果需要a排在b的前边,
则 comp应该返回true。
注意,对于a等于b 情况,一定要返回false。
https://blog.csdn.net/wwlcsdn000/article/details/81711630
##需求概要
既然用到这个排序函数,我们的需求肯定是跟排序有关系的,常见的排序就不用说了。
常见排序举例:
1.单条件排序-- 哪个条件大的排在前边
2.多条件排序(存在优先级)
常见的2-3种条件判断A B C条件可用简单的三层判断解决
先看A,A不相等 ,A大的 满足则在前,不满足在后
先看A,A相等,再看B条件
B条件判断同上
我们来看一个多种条件并且不可按照是否逻辑在区分的条件排序情况(大量情况)
现在有一个排序规则是这样的,需要对物品进行一个按规则的排序。
物品有四大类,装备类型,材料类型,血瓶类型,技能书类型
先根据是否本职业可用排序,可用装备在上,不可用装备在下
再根据装备品质进行排序,品质高的在上,品质低的在下
最后根据装备类型排序,武器>胸甲>鞋子>头盔
材料,血瓶排在可用装备之后,先血瓶再材料,材料也根据品质排序
#需求分析
我们先来简单分析一下物品的排序规则(实际情况我已经做了删减,实际处理可能情况更多)
我现在的排序大种类情况是有11个大类别,每个类别下边可能还会有嵌套2-3个条件判断排序。
如下说思路,
针对一个具体的我们我们首先要分析它是什么种类的属于,
然后针对每个种类可能又需要有单独的排序规则(比如装备品质,等级)
当然规则适用可能又一定的前提条件(比如可穿戴的,不可穿戴无所谓了)
简单梳理下的基本的排序规则情况(从上到下)
本职业可用装备 装备等级 装备品质
血瓶
材料 按品质 高-低
不可用装备
##思路设计
这里我们的排序的规则是没有规律的,所以不能用简单的判断直接返回结果。
首先我们需要定义不同的bool变量去区分基本的是否两种情况(比如是否是装备,是否可穿戴,是否是材料等)
然后我采用了一个单独的自定义规则索引表
用每个索引代表每种情况
比如 1 ---- 可用装备 2------血瓶 3------- 材料 4------------不可用装备
针对每个种类的情况我们有需要单独进行处理
1.可用装备 我们根据装备品质先排序,然后根据装备品质(常规处理)
2.血瓶 无需特殊处理
3.材料 根据材料品质
4.不可用装备 无需特殊处理
##伪代码参考
由于显示等问题最终的结果可能是相反的请自行调整其中的判断关系。
local sort_index = {
equip_yes = 1,
blood = 2,
material = 3,
equip_no = 4,
}
local get_sort_index = function(item)
local id = item.drop_data.item_id
local item_index
local ItemType = CommonItem.Item[id].Type
--first do simple blood and material
if ItemType == const.TYPE_Blood then
item_index = sort_index.blood
return item_index
elseif ItemType == const.TYPE_Material then
item_index = sort_index.material
return item_index
end
local playerType = HeroManager.player.vocation
-- exception handling
if not playerType then
return -1
end
-- equipment
local equiproleType
if EquipItem.equipTemplate[id] then
equiproleType = EquipItem.equipTemplate[id].vocation[1]
end
if equiproleType then
if equiproleType == playerType then
item_index = sort_index.equip_yes
else
item_index = sort_index.equip_no
end
return item_index
end
return -1
end
local equal_sort_index = function(sortA,sortB,A,B)
if not sortA or not sortB then
return false
end
if sortA ~= sortB then
return false
end
local idA = A.id
local idB = B.id
if sortA == sort_index.equip_yes then
local qualityA = CommonItem.Item[idA].Quality
local qualityB = CommonItem.Item[idB].Quality
local levelA = CommonItem.Item[idA].Level
local levelB = CommonItem.Item[idB].Level
if levelA ~= levelB then
return levelA < levelB
end
if levelA == levelB then
return qualityA > qualityB
end
elseif sortA == sort_index.material then
local qualityA = CommonItem.Item[idA].Quality
local qualityB = CommonItem.Item[idB].Quality
if qualityA ~= qualityB then
return qualityA < qualityB
end
else
return false
end
return false
end
--comp way
local comp_pick = function(a,b)
if a == nil or b == nil then
return false
end
local idA = a.id
local idB = b.id
-- if same item
if idA == idB then
return false
end
local sortIndexA = get_sort_index(a)
local sortIndexB = get_sort_index(b)
if sortIndexA == sortIndexB then
-- Sub case do
local result
result = equal_sort_index(sortIndexA,sortIndexB,a,b)
return result
else
return sortIndexA > sortIndexB
end
return false
end
--use way
table.sort(this.youtable,comp_pick)