军事
jssplit(你可能不知道的字符串分割技巧)
ntent='{"url":"","content":"","thumb_url":"https://p6-sign.toutiaoimg.com/tos-cn-i-jcdsk5yqko/314d5e0339ef4c24b89774e667cbc55b~noop.image?x-expires=1671596389&x-signature=aRKELmBlnixUZJrlrPM%2BR9lT2uA%3D","title":"Vue2与Vue3技巧小册","author_description":"前端小智","price":19.9,"share_price":0,"sold":10,"column_id":"7139318513356767492","new_thumb_url":"https://p3-sign.toutiaoimg.com/tos-cn-i-jcdsk5yqko/314d5e0339ef4c24b89774e667cbc55b~noop.image?x-expires=1671596389&x-signature=UKCJmohaUMXijymUno9uG0GzCJ4%3D"}'>

最近看到一个拆分字符串的新方式,就是使用Intl.Segmenteremoji字符串分割成字形的方法。

我以前都没用过这个Intl对象,现在我们一起来看看。

假设你想把用户输入拆分成句子,看起来是一个简单的 split() 任务...但这个问题有很多细微之处。

'Hello! How are you?'.split(/[.!?]/);// ['Hello', ' How are you', '']

使用 split() 会丢失定义的分隔符,并在所有地方包含这些空格。而且因为它依赖于硬编码的分隔符,所以对语言不敏感。

我不懂日语,但你会如何尝试将下面的字符串分割成单词或句子?

// I am a cat. My name is Tanuki.'吾輩は猫である。名前はたぬき。'

普通的字符串方法在这里是没有用的,但是Intl Javascript API 确能解决这个问题。

Intl.Segmenter 来救场

Intl.Segmenter 是一个 Javascript 对象,用于对文本进行区域设置敏感的分段。它可以帮助我们从字符串中提取有意义的项目,如单词、句子或字形。它的使用方式类似于其他的构造函数,可以使用 new 关键字来创建一个 Intl.Segmenter 对象。

const segmenter = new Intl.Segmenter(locale, { granularity: "word" });

在上面的代码中,locale 是字符串,表示要使用的区域设置。granularity 是字符串,表示分段的粒度。它可以是 "grapheme"(字形)、"word"(单词)或 "sentence"(句子)之一。

Intl.Segmenter 有一个很有用的方法叫做 segment(),它可以将文本拆分为有意义的段。

const segments = segmenter.segment(text);

在上面的代码中,text 是要拆分的文本,segments 是返回的段的迭代器。你可以使用 for-of 循环来遍历段,或者使用 Array.from() 将它们转换为数组。

const text = "Hello, world! How are you today?";const segmenter = new Intl.Segmenter("en-US", { granularity: "sentence" });const segments = segmenter.segment(text);for (const segment of segments) {  console.log(segment);}// Output:// { index: 0, value: "Hello, world!", breakType: "", breakIndex: 12 }// { index: 13, value: "How are you today?", breakType: "", breakIndex: 31 }

Intl.Segmenter 对象还有其他一些有用的方法,比如 breakType,用于检索分段的类型(例如,句子的末尾是否包含句号)。另一个有用的方法是 breakType,用于检索分段的类型。

例如:

const text = "Hello, world! How are you today?";const segmenter = new Intl.Segmenter("en-US", { granularity: "sentence" });const segments = segmenter.segment(text);for (const segment of segments) {  console.log(segment.breakType);}// Output:// "exclamation"// "question"

Intl.Segmenter 还有一个很有用的静态方法叫做 supportedLocalesOf(),它可以帮助你确定浏览器是否支持特定的区域设置。

const supported = Intl.Segmenter.supportedLocalesOf(["en-US", "zh-CN"]);console.log(supported);// Output:// ['en-US', 'zh-CN']

在上面的代码中,supported 数组包含浏览器支持的区域设置。

如果你想要对文本进行更细粒度的分段,你可以使用 Intl.ListFormat 对象。它可以帮助你将文本拆分为有意义的列表项。

使用方式类似于 Intl.Segmenter,你可以使用 new 关键字创建一个 Intl.ListFormat 对象。

const listFormat = new Intl.ListFormat(locale, { style: "long", type: "conjunction" });

在上面的代码中,locale 是字符串,表示要使用的区域设置。style 和 type 是对象的属性,用于指定列表格式。style 可以是 "long" 或 "short",type 可以是 "conjunction"(并列)或 "disjunction"(或)。

Intl.ListFormat 有一个很有用的方法叫做 format(),它可以将数组转换为有意义的列表。

const list = ["apple", "banana", "orange"];const formatted = listFormat.format(list);console.log(formatted);// Output:// "apple, banana, and orange"

在上面的代码中,formatted 是转换后的列表字符串。

Word 的颗粒度带有一个额外的isWordLike属性

如果把一个字符串分割成单词,所有的片段都包括空格和换行符。使用isWordLike属性将它们过滤掉。

const segmenterDe = new Intl.Segmenter('de', {  granularity: 'word'});const segmentsDe = segmenterDe.segment('Was geht ab?');console.log([...segmentsDe]);// [//   { segment: 'Was', index: 0, input: 'Was geht ab?', isWordLike: true },//   { segment: ' ', index: 3, input: 'Was geht ab?', isWordLike: false },//   ...// ]console.log([...segmentsDe].filter(s => s.isWordLike));// [//   { segment: 'Was', index: 0, input: 'Was geht ab?', isWordLike: true},//   { segment: 'geht', index: 4, input: 'Was geht ab?', isWordLike: true },//   { segment: 'ab', index: 9, input: 'Was geht ab?', isWordLike: true }// ]

上面通过isWordLike进行过滤会删除标点符号,如.-、或

使用 Intl.Segmenter 来分割 emojis

如果你想把一个字符串分割成可视化的emojis,Intl.Segmenter也是一个很好的帮助。

const emojis = '‍‍‍';// ----// Split by code unitsconsole.log(emojis.split(''));// ['\uD83E', '\uDEE3', '\uD83E', '\uDEF5', '\uD83D', '\uDE48']// ----// Split by code pointsconsole.log([...emojis]);// ['', '', '', '‍', '', '‍', '', '‍', '']// ----// Split by graphemesconst segmenter = new Intl.Segmenter('en', {  granularity: 'grapheme'});const segments = segmenter.segment(emojis);console.log(Array.from(  segmenter.segment(emojis),  s => s.segment));// ['', '', '‍‍‍']

请注意,字形也包括空格和 "正常 "字符。

编辑中可能存在的bug没法实时知道,事后为了解决这些bug,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

参考

  • https://www.stefanjudis.com/today-i-learned/how-to-split-javascript-strings-with-intl-segmenter/
  • https://2ality.com/2022/11/regexp-v-flag.html

原文:https://www.stefanjudis.com/today-i-learned/how-to-split-javascript-strings-with-intl-segmenter/

ntent='{"url":"","content":"","thumb_url":"https://p3-sign.toutiaoimg.com/tos-cn-i-jcdsk5yqko/ddaf55328acf4b878e4db7f18d393ba8~noop.image?x-expires=1671596389&x-signature=SSd%2BFjQOlajJXIU5HcOO5l2nTJM%3D","title":"CSS特效案例","author_description":"前端小智","price":9.99,"share_price":0,"sold":18,"column_id":"7149760885408399649","new_thumb_url":"https://p3-sign.toutiaoimg.com/tos-cn-i-jcdsk5yqko/ddaf55328acf4b878e4db7f18d393ba8~noop.image?x-expires=1671596389&x-signature=SSd%2BFjQOlajJXIU5HcOO5l2nTJM%3D"}'>


顶一下()     踩一下()

热门推荐

发表评论
0评