使用素数解决表示多个标签组合查询
2012-04-06 00:56
344 查看
某一个商品可能有多个标签属性,比如A,B,C,D,E,F,G,H
每个属性分别有出现与不出现的情况。。所有是一个组合的关系 。用一个二进制的字符串或者数字来表示出现与不出现,但是这样要搜索包含某个标签 的时候,得枚举所有的情况,然后以OR的关系去搜索。这样肯定麻烦。。既然要为了存储与索引搜索方便,我暂时想用素数来解决。。
对每一个标签分配一个素数,比如A-》2,B->3,C->5,D->7
这样多个标签的组合就使用他们的乘积作为最终状态。。这样是一种编码的广式,
比如包含A,B,C
则对应的值是2*3*5=30
当然也需要解码,对于给定的一个值30
如果能整除对应的素数集合,则表示包含该标签
30的素数因子为:2,3,5 为相应的标签。简单的实现代码如下。。
这样查询多个状态组合的时候,
每个属性分别有出现与不出现的情况。。所有是一个组合的关系 。用一个二进制的字符串或者数字来表示出现与不出现,但是这样要搜索包含某个标签 的时候,得枚举所有的情况,然后以OR的关系去搜索。这样肯定麻烦。。既然要为了存储与索引搜索方便,我暂时想用素数来解决。。
对每一个标签分配一个素数,比如A-》2,B->3,C->5,D->7
这样多个标签的组合就使用他们的乘积作为最终状态。。这样是一种编码的广式,
比如包含A,B,C
则对应的值是2*3*5=30
当然也需要解码,对于给定的一个值30
如果能整除对应的素数集合,则表示包含该标签
30的素数因子为:2,3,5 为相应的标签。简单的实现代码如下。。
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * @author genuine 房源标签 <br> * 使用素数方式存储 * */ public enum Label { /** * 新推 */ N(2), /** * 随时看房 */ K(3), /** * 视频 */ V(5); /** * 素数 */ private final int primeV; private Label(int v) { this.primeV = v; } public int getPrimeV() { return primeV; } /** * * 通过一个数字找到对应的所有特征 * * @param v * @return */ public static Label[] decodedLabel(int v) { List<Label> list = new ArrayList<Label>(); Label[] labels = Label.values(); int temp = v; for (int i = 0; i < labels.length; i++) { if (temp % labels[i].getPrimeV() == 0) { list.add(labels[i]); temp = temp / labels[i].getPrimeV(); } } if (temp != 1) { System.err.println("是非法值"); return null; } return list.toArray(new Label[list.size()]); } private final static Map<Integer,int[]> cacheIncludeByLabel=new HashMap<Integer,int[]>(); /** * 查询包含某几个标签的时候的所有可能的组合值 * * @param labels * @return */ public static int[] includeByLabel(Label... labels) { if (labels.length < 1) { return null; } //查找缓存,这样可以减少运算 Integer key=encodedLabels(labels); int[] cache = cacheIncludeByLabel.get(key); if(cache!=null){ return cache; } Label[] allLabels = Label.values(); // 获得其它标签 List<Label> otherList = new ArrayList<Label>(allLabels.length); for (int i = 0; i < allLabels.length; i++) { boolean isExist = false; for (int j = 0; j < labels.length; j++) { if (allLabels[i].getPrimeV() == labels[j].getPrimeV()) { isExist = true; } } if (!isExist) { otherList.add(allLabels[i]); } } int sum = 1; for (int i = 0; i < labels.length; i++) { sum *= labels[i].getPrimeV(); } final int otherSize = otherList.size(); final int size = otherSize * 2; final int[] includeV = new int[size]; int pos = 0; includeV[pos++] = sum;// 纯包含指定的label // 计算不同的组合的值 for (int i = pos; i < size; i++) { int[] compose = new int[otherSize]; toBinary(i, compose); int tempSum = sum; for (int j = 0; j < otherSize; j++) { if (compose[j] == 1) { tempSum *= otherList.get(j).getPrimeV(); } } includeV[i] = tempSum; } //缓存 cacheIncludeByLabel.put(key, includeV); return includeV; } /** * 通过多个标签返回最终数字 * 如果参数非法则会返回值1 * @param labels * @return */ public static int encodedLabels(Label[] labels) { if (labels == null) { return 1; } int sum = 1; for (int i = 0; i < labels.length; i++) { sum *= labels[i].getPrimeV(); } return sum; } public static int encodedLabel(Label label) { if (label == null) { return 1; } return label.getPrimeV(); } /** * 通过多个标签返回最终数字 * 如果参数非法则会返回值1 * @param labels * @return */ public static int encodedLabels(Iterator<Label> labels) { if (labels == null) { return 1; } int sum = 1; while (labels.hasNext()) { sum *= labels.next().getPrimeV(); } return sum; } /** * 给定数字,返回该数字的二进制表示并存在一个int数组中 */ private static void toBinary(int inputNum, int[] result) { int pos = result.length; do { result[--pos] = inputNum & 1; inputNum >>>= 1; } while (inputNum != 0); } public static void main(String[] args) { // int i = 15; // Label[] label = Label.getLabel(i); // // for (int j = 0; j < label.length; j++) { // System.out.println(label[j]); // } // // System.out.println("------------------------------"); Label k = Label.K; Label n = Label.N; int a[] = Label.includeByLabel(n, k); System.out.println(Arrays.toString(a)); } }
这样查询多个状态组合的时候,
相关文章推荐
- MyBatis中使用bind标签构造模糊查询失败的解决方法
- 关于存储过程中一个参数表示多个查询条件使用方法的简单处理
- Jeecg中使用<t: dgCol>标签的自动构造查询条件时出现类型转换错误的解决办法。
- 网站后台登录aspcms 提示错误号:-2147467259,错误描述:操作必须使用一个可更新的查询。sql=update AspCms_Content set TimeStatus=0 where TimeStatus=1 and Timeing <= 解决方法。
- 使用pymongo.find查询很慢的解决方式
- 解决php 处理 form 表单提交多个 name 属性值相同的 input 标签问题
- 解决"操作必须使用一个可更新的查询"问题
- 使用Criteria查询级联表时出现的问题及解决
- Microsoft JET Database Engine 错误 '80004005' 操作必须使用一个可更新的查询。解决方法
- 使用PDO连接数据库 查询和插入乱码的解决方法
- 使用CSS3中的input标签与lable标签组合实现banner图的切换
- 使用append出的标签用on绑定事件无效的解决方法
- JSP使用base标签和时间控件时IE6下不能打开站点,已终止操作问题解决
- spring使用@Value标签读取.properties文件的中文乱码问题的解决
- 本地使用JSTL标签的方式及问题解决
- RelativeLayout中使用include标签对齐不起作用解决方法
- hibernate使用hql跨表查询遇到的问题以及解决方式
- 取从textarea中存到MYSQL的数据以原格式显示问题以及解决MySQL日期处理和标签的使用
- sql这两个表和查询的组合yii通过使用数据库查询
- 使用oledb读写excel出现“操作必须使用一个可更新的查询”的解决办法