创作目的

国内对于文本的相似度计算,开源的工具是比较丰富的。

但是对于两个汉字之间的相似度计算,国内基本一片空白。国内的参考的资料少的可怜,国外相关文档也是如此。

本项目旨在抛砖引玉,实现一个基本的相似度计算工具,为汉字 NLP 贡献一点绵薄之力。

推荐阅读:

NLP 中文形近字相似度计算思路

中文形近字相似度算法实现,为汉字 NLP 尽一点绵薄之力

当代中国最贵的汉字是什么?

NLP 开源形近字算法补完计划(完结篇)

NLP 开源形近字算法之形近字列表(番外篇)

开源项目在线化 中文繁简体转换/敏感词/拼音/分词/汉字相似度/markdown 目录

需求

有时候我们并不是需要返回两个字的相似,而是需要返回一个汉字的相似列表。

实现思路

我们可以分别计算所有的汉字之间的相似度,然后保留最大的前100个,放在字典中。

然后实时查询这个字典即可。

实现方式

bihuashu_2w.txt 中我们主要需要的是对应的 2W 常见汉字。

hanzi_similar_list.txt 用来存放汉字和相似字的映射关系。

数据初始化

public static void main(String[] args) {
final String path = "D:\\code\\coin\\nlp-hanzi-similar\\src\\main\\resources\\hanzi_similar_list.txt";
// 读取列表
List<String> lines = FileUtil.readAllLines("D:\\code\\coin\\nlp-hanzi-similar\\src\\main\\resources\\nlp\\bihuashu_2w.txt");
// 所有的单词
Set<String> allWordSet = new HashSet<>();
for(String line : lines) {
String word = line.split(" ")[0];
allWordSet.add(word);
}
// 循环对比
for(String word : allWordSet) {
List<String> list = getSimilarListData(word, allWordSet);
String line = word +" " + StringUtil.join(list, "");
FileUtil.append(path, line);
}
}
  • 优先级队列取前 100 个

我们通过优先级队列存储:

private static List<String> getSimilarListData(String word, Set<String> wordSet) {
PriorityQueue<SimilarListDataItem> items = new PriorityQueue<>(new Comparator<SimilarListDataItem>() {
@Override
public int compare(SimilarListDataItem o1, SimilarListDataItem o2) {
// 相似度大的放在前面
return -o1.getRate().compareTo(o2.getRate());
}
});
for(String other : wordSet) {
if(word.equals(other)) {
continue;
}
// 对比
double rate = HanziSimilarHelper.similar(word.charAt(0), other.charAt(0));
SimilarListDataItem item = new SimilarListDataItem(other, rate);
items.add(item);
}
final int limit = 100;
List<String> wordList = new ArrayList<>();
for(SimilarListDataItem item : items) {
wordList.add(item.getWord());
if(wordList.size() >= limit) {
break;
}
}
return wordList;
}

相似字的获取

初始化好数据之后,一切就变得非常简单:

  • 接口定义
/**
* 数据接口-相似列表
* @author binbin.hou
* @since 1.3.0
*/
public interface IHanziSimilarListData { /**
* 返回数据信息
* @param word 单词
* @return 结果
* @since 1.3.0
*/
List<String> similarList(String word); }
  • 数据获取
public class HanziSimilarListData implements IHanziSimilarListData {

    private static volatile Map<String, List<String>> map = Guavas.newHashMap();

    @Override
public List<String> similarList(String word) {
if(MapUtil.isEmpty(map)) {
initDataMap();
} return map.get(word);
} private void initDataMap() {
if(MapUtil.isNotEmpty(map)) {
return;
} //DLC
synchronized (map) {
if(MapUtil.isEmpty(map)) {
List<String> lines = StreamUtil.readAllLines("/hanzi_similar_list.txt"); for(String line : lines) {
String[] words = line.split(" ");
// 后面的100个相近词
List<String> list = StringUtil.toCharStringList(words[1]);
map.put(words[0], list);
}
}
}
} }

便利性

为了用户使用方便,我们在 HanziSimilarHelper 中添加 2 个工具类方法:

/**
* 相似的列表
* @param hanziOne 汉字一
* @param limit 大小
* @return 结果
* @since 1.3.0
*/
public static List<String> similarList(char hanziOne, int limit) {
return HanziSimilarBs.newInstance().similarList(hanziOne, limit);
}
/**
* 相似的列表
* @param hanziOne 汉字一
* @return 结果
* @since 1.3.0
*/
public static List<String> similarList(char hanziOne) {
return similarList(hanziOne, 10);
}

测试效果

我们使用看一下效果:

我们来看一下【爱】的形近字。

List<String> list = HanziSimilarHelper.similarList('爱');
Assert.assertEquals("[爰, 爯, 受, 爭, 妥, 憂, 李, 爳, 叐, 雙]", list.toString());

开源地址

为了便于大家使用学习,项目已开源。

https://github.com/houbb/nlp-hanzi-similar

小结

一个字的形近字可以做很多有趣的事情,这个要看大家的想象力。

实现方式也不难,最核心的还是相似度的计算。

我是老马,期待与你的下次重逢。

NLP 开源形近字算法之相似字列表(番外篇)的更多相关文章

  1. NLP 开源形近字算法补完计划(完结篇)

    前言 所有的故事都有开始,也终将结束. 本文将作为 NLP 汉字相似度的完结篇,为该系列画上一个句号. 起-NLP 中文形近字相似度计算思路 承-中文形近字相似度算法实现,为汉字 NLP 尽一点绵薄之 ...

  2. KMP算法番外篇--求解next数组

    KMP算法实现字符串的模式匹配的时间复杂度比朴素的模式匹配好很多,但是它时间效率的提高是有前提的,那就是:模式串的重复率很高,不然它的效率也不会凸显出来.在实际的应用中,KMP算法不算是使用率很高的一 ...

  3. 数据结构和算法 – 番外篇.时间测试类Timing

    public class Timing { //startingTime--用来存储正在测试的代码的开始时间. TimeSpan startingTime; //duration--用来存储正在测试的 ...

  4. CWMP开源代码研究番外篇——博通方案

    声明:本篇文章来自于某公司Cable Modem产品的文档资料,源码来自于博通公司,只提供参考(为保护产权,本人没有源码). 前文曾提到会写一篇关于博通的tr069,那么福利来了.福利,福利,福利,重 ...

  5. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记番外(1) - JLinkScript妙用

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记番外篇之JLinkScript妙用. JLinkScript 文件是配套 J-Link 调试器使用的脚本,这个脚本适 ...

  6. Java实现 蓝桥杯 算法提高 周期字串

    算法提高 周期字串 时间限制:1.0s 内存限制:256.0MB 问题描述 右右喜欢听故事,但是右右的妈妈总是讲一些"从前有座山,山里有座庙,庙里有个老和尚给小和尚讲故事,讲的什么呢?从前有 ...

  7. zz【清华NLP】图神经网络GNN论文分门别类,16大应用200+篇论文最新推荐

    [清华NLP]图神经网络GNN论文分门别类,16大应用200+篇论文最新推荐 图神经网络研究成为当前深度学习领域的热点.最近,清华大学NLP课题组Jie Zhou, Ganqu Cui, Zhengy ...

  8. Duang的成长——使用造字程序输入生僻字

    使用造字程序输入生僻字 最近,一个字突然间火了起来,那就是——duang! (图片来自网络) 那么,问题来了!造字程序哪家强?(此处有掌声) 其实,微软早就考虑到各国文字的博大精深,在系统中集成了一个 ...

  9. 【开源.NET】轻量级内容管理框架Grissom.CMS(第三篇解析配置文件和数据以转换成 sql)

    该篇是 Grissom.CMS 框架系列文章的第三篇, 主要介绍框架用到的核心库 EasyJsonToSql, 把标准的配置文件和数据结构解析成可执行的 sql. 该框架能实现自动化增删改查得益于 E ...

  10. 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(Unified API篇)

    SDK 开发 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(理念与设计原则篇) 顶级开源项目 Sentry 20.x JS-SDK 设计艺术(开发基础篇) 顶级开源项目 Sentry ...

随机推荐

  1. windows elasticsearch 7.9.3安装

    1.JDK,我用的是OPEN JDK https://jdk.java.net/    通过CMD设定java环境变量设置    set java_home=C:\Program Files\java ...

  2. 智利SUBTEL更新WiFi 6技术法规!

    2022年9月6日,智利电信监管机构(SUBTEL) 发布了第2844号豁免决议,更新了1985号豁免决议,即短程设备的固定技术标准. 主要更新如下: • 2.4 GHz频段已在医疗设备目录中删除,现 ...

  3. MyBatis面试题汇总

    1.什么是Mybatis? Mybatis是对象关系映射一个框架,它内部封装了JDBC,开发的时候只要关注SQL语句本身,可以严格控制sql的执行性能,灵活,其二可以通过XML或者注解来配置映射信息 ...

  4. 接口返回JSON字符串压缩和解压

    using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.IO;usi ...

  5. vs xamarin获取sha1申请百度sdk密钥

    请查看微软帮助文档 查找密钥存储的签名 - Xamarin | Microsoft Docs

  6. 12.20linux学习第十九天

    今天老刘开始讲第17章 使用iSCSI服务部署网络存储.第18章 使用MariaDB数据库管理系统和第19章 使用PXE+Kickstart无人值守安装服务,内容有点多. 7.1 iSCSI技术介绍 ...

  7. win10系统格式化后进行虚拟分区

    1. 目的 目前win10磁盘分区多数人采用两种方式: 1:只分一个C盘,文件在C盘以目录区分. 缺点:所有文件都在一起,区分查找比较麻烦. 2:物理分区,分多个盘,如C,D,E等等 缺点:容量固定, ...

  8. FCC 中级算法题 Everything Be True

    Everything Be True 所有的东西都是真的! 完善编辑器中的every函数,如果集合(collection)中的所有对象都存在对应的属性(pre),并且属性(pre)对应的值为真.函数返 ...

  9. oracle 用户连接数查询

    oracle 用户连接数查询 --当前的连接数 select count(*) from v$session; --数据库允许的最大连接数 select value from v$parameter ...

  10. python高阶编程(二)

    1.迭代器 迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问结束.迭代器只能往下不会后退. 我们已经知道,可以直接作用于f ...