复选框与bitmap算法实践

bitmap(位图)算法

bitmap算法是利用数据二进制的每一位的值来表示数据的算法,可用来压缩保存数据集

如何保存

如 5(int)的二进制表示为 101b,第一位和第三位的值是1就可以表示数据集 {1,3} ,也就是1个int类型,最多可以保存包含 32个int(4字节32位)的数据集(即表示数字1-32的集合),如果用字符保存,char是2字节16位(纯数字用啥字符类型),都是极大节省了存储空间。

如何存储到数据库

一般数据库可以表示整型类型有int,long(bigint),decimal等,可按需选择,不够再做调整。


复选框存储

在实际生产中,我们经常会碰到包含复选框的表单开发,大部分都是直接使用一个字符串加上逗号等特殊符号分隔进行存储。如"1,3,5"这种形式存储,代码处理选中时再分隔成List去判断是否包含,相信很多人都这样做过。这样的好处是存储的数据会更直观,却不便于sql查询(暴力模糊查询)

适用bitmap场景

枚举值较多,数据量较大(like匹配不走索引),复杂查询统计。

代码实现

枚举定义

枚举值为2的n次方,使用Flags特性,标识这个是标记枚举(用不用重载的方法不重要,重要的是规范,做为一个标识),会被用来进行(位)运算

[Flags]
public enum DefaultMerchantType
{
	/// <summary>
	/// 一单一付
	/// </summary>
	[Description("一单一付")]
	OneOrderOnePay = 1,

	/// <summary>
	/// 非T+N
	/// </summary>
	[Description("非T+N")]
	NoTN = 2,

	/// <summary>
	/// T+N
	/// </summary>
	[Description("T+N")]
	TN = 4,
}

页面渲染

通过位运算&判断是否选中,sql也是同理。

<td>
	@{
		var enumDtos = typeof(DefaultMerchantType).GetFields().Skip(1).Select(e => new
		{
			EnumValue = (int)e.GetValue(null),
			EnumDesc = (e.GetCustomAttributes()
					.Where(ac => ac.GetType() == typeof(System.ComponentModel.DescriptionAttribute)).FirstOrDefault()
					as System.ComponentModel.DescriptionAttribute).Description,
		}).ToList(); ;
	}
	@for (int i = 0; i < enumDtos.Count; i++)
	{
		<label>
			@Html.CheckBox("DefaultAccountList[" + i + "]", (Model.DefaultAccount & enumDtos[i].EnumValue) == enumDtos[i].EnumValue)@enumDtos[i].EnumDesc;
		</label>
	}
</td>

表单项转int存储

后台接收到list,再转成Int存储,注意Reverse()将复选框的顺序值进行反转,如1010b,展示顺序是0,1,0,1

public class BitMapHelper
{
    //将复选框的List转成int存储
	public static int CheckListToInt(List<bool> checks)
	{
		if (checks == null || !checks.Any())return 0;
		return Convert.ToInt32(new string(checks.Select(r => r ? '1' : '0').Reverse().ToArray()),2);
	}
}
原文地址:https://www.cnblogs.com/zk-ljc/p/12205634.html