背景:
产品提出需求,一个申请单需要客户自定义字段名和字段值进行排序,并且指定各个排序规则的优先级,如:先根据急诊和普诊排序然后再根据军人,普通人排序,然后再根据其他的规则排序。规则用户可以自定义。
实现:
1:用户可以自定义类的字段名称并且可以自定义值的List<>,如:sex: “女”,"男"。
2:用户第一定义多个1的规则,并有顺序
具体算法实现是:
是采用每项打分的方法,因为规则有顺序,所以第一个规则较贵分值的粒度为1,下面的分值的粒度依次为0.1,0.01,0.001
那么背景中描述的第一个规则急诊和普诊规则分数依次为2和1,第二个规则军人和普通人分数依次为0.2和0.1等等依次类推
代码实现如下:
可以调用 new PaiXu().goTest();查看测试排序代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
namespace AllTestProject
{
public class PaiXu
{
private static readonly List<string> RankList = new List<string>() { "主席", "部长", "省长", "市长", "科长", "职员" };
private static readonly List<string> SexList = new List<string>() { "女", "男", "未知" };
private static readonly List<string> FeatureList = new List<string>() { "孕妇", "残疾人", "老人", "小孩", "普通人" };
Dictionary<string, List<string>> propertyDictionary = new Dictionary<string, List<string>>()
{
{"Rank",RankList},
{"Sex",SexList},
{"Feature",FeatureList}
};
public static Random random = new Random(Guid.NewGuid().GetHashCode());
public void goTest()
{
var cc = Sort<People>(getTestList());
}
private List<People> getTestList()
{
List<People> peoples = new List<People>();
for (int i = 0; i < 100; i++)//造测试数据
{
peoples.Add(new People()
{
Feature = FeatureList[random.Next(0, 5)],
Rank = RankList[random.Next(0, 6)],
Sex = SexList[random.Next(0, 3)]
});
}
return peoples;
}
private IEnumerable<T> Sort<T>(List<T> peoples)
{
int peopleIndex = 0;
var sortResList = new Dictionary<int, decimal>();//这个是最后的结果
foreach (var people in peoples)
{
var peopleType = people.GetType();
var sortNumList = new List<decimal>();
foreach (var key in propertyDictionary.Keys)
{
Trace.Assert(peopleType.GetProperty(key) != null);
var value = peopleType.GetProperty(key).GetValue(people, null).ToString();
decimal score = 0;
var itemIndex = propertyDictionary[key].FindIndex(a => a == value);//是否等于某个排序项
if (itemIndex < 0)
{
sortNumList.Add(0);
}
else
{
sortNumList.Add(propertyDictionary[key].Count - itemIndex);//这个是根据第一个应该是最靠前的,所以第一的下标是最大的
}
}
decimal interval = 1;
decimal resDecimal = 0;
foreach (var sortNum in sortNumList)
{
resDecimal += sortNum * interval;
interval = interval * (decimal)0.1;
}
sortResList.Add(peopleIndex, resDecimal);
peopleIndex++;
}
var newPeoples = new List<T>();
foreach (int index in sortResList.OrderBy(a => a.Value).Select(a => a.Key).ToList())
{
newPeoples.Add(peoples[index]);
}
return newPeoples;
}
}
public class People
{
/// <summary>
/// 职级,主席,部长,省长,市长,科长,职员
/// </summary>
public string Rank { get; set; }
/// <summary>
/// 性别,女男未知
/// </summary>
public string Sex { get; set; }
/// <summary>
/// 老人小孩儿等属性
/// </summary>
public string Feature { get; set; }
}
}