阅读视图

发现新文章,点击刷新页面。

前端文本分割工具,“他”来了

大家好,我是CC,在这里欢迎大家的到来~

简介

在日常开发场景中大多数是使用空字符串、空格或者换行符来进行文本分割。现在可以试试新的分割工具-Intl.Segmenter

Intl.Segmenter 支持根据语言进行的文本分割,将一个字符串分割成片段,分割类型包括字、词和句。

试试分割效果

以简体中文为例,这里我们先设置按照词(word)分割:

按词分割-多语言分词

const segmenter = new Intl.Segmenter("zh-Hans-CN", { granularity: "word" });
const string = "前端文本分割工具,“他”来了";

const iterator = segmenter.segment(string)[Symbol.iterator]();

for(let item of iterator) {
  console.log(item.segment);
}
// 前端
// 文本
// 分割
// 工具
// ,
// “
// 他
// ”
// 来
// 了

效果还不错,有点类似词义分割了。再看看其他分割方式。

按字分割(默认)-处理复杂字符

在简体中文场景下效果与'前端文本分割工具,“他”来了'.split("")相同。

const segmenter = new Intl.Segmenter("zh-Hans-CN", { granularity: "grapheme" });
const string = "前端文本分割工具,“他”来了";

const iterator = segmenter.segment(string)[Symbol.iterator]();

for(let item of iterator) {
  console.log(item.segment);
}
// 前
// 端
// 文
// 本
// 分
// 割
// 工
// 具
// ,
// “
// 他
// ”
// 来
// 了

按句分割-多语言句子分析

加了分号、感叹号、问号、句号这些标点符号,还是可以完整分割出来的。

const segmenter = new Intl.Segmenter("zh-Hans-CN", { granularity: "sentence" });
const string = "前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了。前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了!前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了?";

const iterator = segmenter.segment(string)[Symbol.iterator]();

for(let item of iterator) {
  console.log(item.segment);
}
// 前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了。
// 前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了!
// 前端文本分割工具,“他”来了,前端文本分割工具,“他”来了;前端文本分割工具,“他”来了?

完整数据格式

实际上分割出来的每个单位都是一个 JSON 对象,除了 segment 代表文本内容外,还有 index 代表索引、input 表示原文本完整内容、isWordLike 表示是否像文本单词(如果是标点符号类型的就会是 false)。

{
    "segment": "前端",
    "index": 0,
    "input": "前端文本分割工具,“他”来了",
    "isWordLike": true
}

分割的参数

locales

当然除了简体中文,Intl.Segmenter 也支持其他语言。

Intl.Segmenter 的第一个参数 locales 支持填写带有 BCP 47 语言区域标记的一个字符串,或者一个这样的字符串数组。

在 BCP 47 中表示语言、脚本、国家(区域)和变体(少用)的语言子标记含义可以在IANA 语言子标记注册 中找到。

localeMatcher

Intl.Segmenter 的第二个参数中除了可以选择如何分割外,还可以根据 ****locales ****在 ****lookup ****和 ****best fit ****之间选择一个匹配算法来配置 localeMatcher 参数。

best fit

默认值,运行时可能会选择一个可能比查找算法的结果更加合适的语言区域。

lookup

使用 BCP47 查找算法从 locales 参数中选择语言区域。像如果运行时支持 "de" 但不支持 "de-CH",用户传入的 "de-CH" 可能就会以 "de" 为结果进行使用。

分割对象的方法

分割字符串

上文中对分割文本对象进行分割的 segment 方法。

判断返回支持的 locale

在给定的 locales 数组中判断出 Segmenter支持的 locales。但是可能每个浏览器支持的不大一样。

const locales = ["ban", "id-u-co-pinyin", "de-ID"];
const options = { localeMatcher: "lookup" };
console.log(Intl.Segmenter.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

获取分割对象的配置参数

const spanishSegmenter = new Intl.Segmenter("es", { granularity: "sentence" });
const options = spanishSegmenter.resolvedOptions();

console.log(options.locale); // "es"
console.log(options.granularity); // "sentence"

在参数不支持的情况下会取当前运行环境中默认语言环境。

const banSegmenter = new Intl.Segmenter("ban");
const options = banSegmenter.resolvedOptions();

console.log(options.locale); // "zh-CN"
console.log(options.granularity); // "grapheme"

总结

Intl.Segmenter 很适合在文本处理场景下使用,给了一定的分割标准。它在文本编辑器中计算光标索引、搜索建议的生成、文本计算长度和文本过滤,甚至在自然语言处理场景中都可以使用到。

目前在 fabric.js 中也在考虑使用 Intl.Segmenter 来优化文本分割,可以研究学习。

大家可能也注意到了,Segmenter 只是 Intl 下的一个对象,还有针对像数字、复数、日期、地区等国际转化,这些后续去研究。

❌