百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

你可能不知道的字符串分割技巧_excel分割字符串split

itomcoil 2025-02-19 12:22 6 浏览

最近看到一个拆分字符串的新方式,就是使用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 units
console.log(emojis.split(''));
// ['\uD83E', '\uDEE3', '\uD83E', '\uDEF5', '\uD83D', '\uDE48']

// ----
// Split by code points
console.log([...emojis]);
// ['', '', '', '?', '', '?', '', '?', '']

// ----
// Split by graphemes
const 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/

相关推荐

使用 Rust 和 Tokio 构建 TCP 服务器示例

Tokio是一个用于构建异步应用程序的Rust框架,其核心特点是使用了基于事件循环的模型,可以实现高效的异步IO操作。在本文中,我们将通过一个示例程序来了解如何使用Tokio来构建一个基...

使用 Rust Rocket 构建高性能的实时通信应用

在这个实时通信盛行的时代,WebSocket技术已经成为现代Web应用不可或缺的一部分。而Rust作为一门安全高效的系统级编程语言,正在Web开发领域崭露头角。今天,我们将探索如何利用Rust的Roc...

安利一款免费、开源、实时的服务器监控工具:Netdata

Netdata是一个免费、开源、实时的服务器监控工具,可以可视化和监控实时数据,如CPU使用率、RAM使用率、负载、SWAP使用率、带宽使用率、磁盘使用率等。它可以帮助系统管理员了解您的系统...

Rust+Tauri2+React+TS剪切板管理桌面端应用开发示例

随着Tauri2.0的发布,Tauri越来越值得关注,当然与名气更大的Electron相比仍有差距,但因其有Rust加持,仍表现出很大潜力,如果想开发【小而美】的桌面端App,Tauri是个不错的选择...

Tokio全攻略:Rust异步编程的终极指南

Tokio是Rust语言中一个非常流行的异步运行时(AsynchronousRuntime),它使得编写异步代码变得简单而高效。Tokio提供了强大的功能,包括异步I/O、定时器、多线程执行器等,是...

14 张图搞懂 Nginx 高性能网络工作原理 简单粗暴

在单进程的网络编程模型中。所有的网络相关的动作都是在一个进程里完成的,如监听socket的创建,bind、listen。再比如epoll的创建、要监听事件的添加,以及epoll_wait...

魔兽世界单机版GM命令大全

看完GM命令发现游戏角色改名、改阵营真的是无本经营啊。现分享一下AZ端、TC端的GM命令,大差不差。添加了其它mod的朋友需要去自行去查看源码。例如:添加了个人经验倍率调整mod,会多出.xpen...

如何修改 Nginx 源码实现 worker 进程隔离

背景最近我们线上网关替换为了APISIX,也遇到了一些问题,有一个比较难解决的问题是APISIX的进程隔离问题。APISIX不同种类请求的互相影响首先我们遇到的就是APISIXPromet...

nginx源码剖析—nginx进程模型

1.nginx进程模型nginx采用的是多进程模型,典型的master-worker方式,采用一个masterprocess(监控进程,也叫做主进程)和多个wokerprocess(工作进程)的设...

C++异步从理论到实践总览篇

C++20带来了coroutine特性,同时新的execution也在提案过程中,这两者都给我们在C++中解决异步问题带来了新的思路.但对比其他语言的实现,C++的协程和后续的executio...

从C++到Rust:开启系统编程新征程

从C++到Rust:开启系统编程新征程c++程序员的rust入门教程Rust:C++程序员的新选择在当今的编程世界中,C++凭借其高效、灵活以及对底层硬件的直接操控能力,一直是系统编程、游戏开发、...

深入理解Python subprocess模块

subprocess是Python中用于创建和管理子进程的核心模块,它取代了旧有的os.system和os.spawn*方法,提供了更灵活、安全的进程交互能力。以下是深入理解该模块的关键...

一键释放iOS 64位App潜力

作者:eddiecmchen,PCG客户端开发工程师|导语把我的iPhoneXR扶起来,它还能再顶一会儿~背景远在iOS11时期(2017年),苹果就发公告要求所有需要上架AppStore的应...

第五十天-ceontOS6.8上安装vsftpd

学习笔记:1.FTP协议有两种工作方式:PORT方式和PASV方式,中文意思为主动式和被动式。一、PORT(主动)方式的连接过程是:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连...

PS小技巧 调整命令,让人物肤色变得更加白皙 #后期修图

我们来看一下如何去将人物的皮肤变得更加的白皙。·首先选中图层,Ctrl键加J键复制一层。·打开这里的属性面板,选择快速操作删除背景,这样就会将人物进行单独的抠取。·接下来在上方去添加一个黑白调整图层,...