字符串进行前缀匹配

问题

工作中接到这样一个需求
货品编号的前缀是由分类的编号组成的, 用户输入货品编号的时候自动回显出货品的分类.
而 货品的分类编号是不规则的
如: 0401,020508,27800101
每一个编号的长度都是不同的, 不过好在是相同数组开头的编号长度都是统一的.
所以不免有些人会冒出写死匹配的想法. 但是这也太low了.
经过不懈的尝试和努力终于找到了两种解决方案.

第一种

得到货品编号的时候, 以步长为1 从后向前依次截取字符串, 将截取后的字符串去分类编号中进行匹配,如匹配到了则将分类信息返回, 如匹配不到则继续进行匹配,直到匹配到为止;

代码示例

	public GoodsCategoryEntity getByGoodsIdnumber(String goodsIdnumber) {
		// 获取所有的分类信息
		List<GoodsCategoryEntity> list = this.list();
		// 以编码为key, 转换成map集合
		Map<String, GoodsCategoryEntity> goodsCategoryMap = list.stream().collect(Collectors.toMap(GoodsCategoryEntity::getIdnumber, Function.identity()));
		// 调用编码截取匹配方法
		GoodsCategoryEntity goodsGategory = getGoodsGategory(goodsIdnumber, goodsCategoryMap);
		return goodsGategory;
	}

	//从货品编码中匹配出货品分类编码
	private GoodsCategoryEntity getGoodsGategory(String goodsIdnumber,  Map<String, GoodsCategoryEntity> goodsCategoryMap) {
		if (Func.isBlank(goodsIdnumber)) {
			return new GoodsCategoryEntity();
		}
		// 进行字符串截取
		String substring = goodsIdnumber.substring(0, goodsIdnumber.length() - 1);
		// 如果截取出的编码匹配到了分类信息则返回, 没匹配到则进行递归继续匹配
		return Func.isEmpty(goodsCategoryMap.get(substring))?getGoodsGategory(substring, goodsCategoryMap):goodsCategoryMap.get(substring);
		
	}

第二种

其实思想同上述方法差不多,只不过上述方法是从后往前匹配, 该方法是从前往后匹配;
从前往后就要比从后往前多考虑一些, 因为分类编码存在父子级关系
比如: 04 和 0401 和 040101
所以不能匹配到一个就结束.

上代码

# 首先要创建一个前缀树

public class Trie implements Serializable {

	private static final long serialVersionUID = 1L;

    public static class Node{
		public Map<Character, Node> children = new HashMap<>();
    }

	public Node root = new Node();
    public Trie() {

    }
	// 将元素填入前缀字典中
    public void insert(String word) {
        Node pre = this.root;
        for(char c: word.toCharArray()){
            Node node = pre.children.get(c);
            if(node == null){
                node = new Node();
                pre.children.put(c, node);
            }
            pre = node;
        }
    }
	// 查询前缀并返回前缀
    public String search(String word) {
        Node pre = this.root;
		String str = "";
        for(char c: word.toCharArray()){
            Node node = pre.children.get(c);
            if(node == null) return str;
			str = str + c;
            pre = node;
        }
        return str;
    }
}
	public GoodsCategoryEntity getByGoodsIdnumber(String goodsIdnumber) {
		// 获取所有的分类信息
		List<GoodsCategoryEntity> list = this.list(Wrappers.lambdaQuery(GoodsCategoryEntity.class).select(GoodsCategoryEntity::getIdnumber));
		// 填充好前赘树
		Trie  trie = new Trie();
		for (GoodsCategoryEntity category : list) {
			trie_map.insert(string);	
		}
		# 以上步骤可以提前预制好, 并将trie对象序列化存在缓存中, 在使用时直接从缓存中获取 trie 对象

		// 进行编码匹配
		String number = trie_map.search(goodsIdnumber);
		// 通过编码获取分类对象
		GoodsCategoryEntity entity = this.getOne(Wrappers.lambdaQuery(GoodsCategoryEntity.class).eq(GoodsCategoryEntity::getIdnumber,number ));
		return Func.isEmpty(entity )?new GoodsCategoryEntity ():entity;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值