【资源链接】
链接:https://pan.baidu.com/s/1NSH5T0qkTTcOJbURd9Mq7A
提取码:nnx6
【包含文件】
1.需求说明
由于项目需要通过姓名判断性别,在网络上找到了Python
的NGender
包,但项目的技术栈是Java
,首先想到的是使用jython-standalone
来执行 Python 代码,在 idea 成功调用,在部署时却无法找到NGender
模块,最终无法解决部署问题因此有了 Java 版本的 NGender 😄 有成功部署的小伙伴儿可以分享一下经验。Java 版本说明:
- 82%的准确率(与python版本一致)
- 可用于猜测性别
- 可用于判断名字的男性化/女性化程度
2.代码实现
2.1 依赖
用于解析csv
类型文件,非必须依赖,可自行解析。
<!-- 用于解析csv文件 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.6.6</version> </dependency>
2.2 源码
源码从 Python 代码转化,并未进行优化。
@Slf4j @Component public class GenderUtils { private Map<String, String> genderMap = new HashMap<>(9443); private int maleTotal = 0; private int femaleTotal = 0; private int genderTotal = 0; @PostConstruct private void init() { // 加载文件 File toFile = new File("data/ngender/charfreq.csv"); // 解析CSV文件 CsvData rows = CsvUtil.getReader().read(toFile); for (int i = 1, rowCount = rows.getRowCount(); i < rowCount; i++) { CsvRow row = rows.getRow(i); maleTotal += Integer.parseInt(row.get(1)); femaleTotal += Integer.parseInt(row.get(2)); } genderTotal = maleTotal + femaleTotal; // 封装对象 for (int i = 1, rowCount = rows.getRowCount(); i < rowCount; i++) { CsvRow row = rows.getRow(i); String nameChar = row.get(0); int maleNum = Integer.parseInt(row.get(1)); int femaleNum = Integer.parseInt(row.get(2)); genderMap.put(nameChar, 1.0 * femaleNum / femaleTotal + "," + 1.0 * maleNum / maleTotal); } } /** * 根据姓名判断性别(仅支持中文) * * @param nameString 姓名 * @return 性别信息 */ public Map<String, String> guessGenderByName(String nameString) { // 截取【名】的全部字符字符 char[] nameChars = nameString.substring(1).toCharArray(); // 获取性别可能性数据 double maleProb = getGenderProb(nameChars, 1); double femaleProb = getGenderProb(nameChars, 0); // 返回结果 if (maleProb > femaleProb) { return new HashMap<String, String>(2) {{ put("male", String.valueOf(maleProb / (maleProb + femaleProb))); }}; } else if (femaleProb > maleProb) { return new HashMap<String, String>(2) {{ put("female", String.valueOf(femaleProb / (maleProb + femaleProb))); }}; } else { return new HashMap<String, String>(2) {{ put("unknown", "0"); }}; } } /** * 计算性别可能性 * * @param nameChars 【名】的全部字符字符 * @param genderFlag 0 female 1 male * @return 性别及可能性 */ private double getGenderProb(char[] nameChars, int genderFlag) { double baseProb; if (genderFlag == 0) { baseProb = 1.0 * femaleTotal / genderTotal; } else { baseProb = 1.0 * maleTotal / genderTotal; } for (char nameChar : nameChars) { baseProb *= Double.parseDouble(MapUtils.getString(genderMap, nameChar + "", "0,0").split(",")[genderFlag]); } return baseProb; } }
2.3 调用
charfreq.csv
文件有9943条,整个工具类的加载需要88ms【仅测试一次】
。
Map<String, String> resultMap = genderUtils.guessGenderByName("刘芳芳"); // "female": "0.9835037905504539"
3.其他
Python 版本的 NGender 下载地址 及介绍。