目的是从一个阿拉伯字符串中找到并删除一个起始字符串/字符/单词,我们不知道它是否有变音符号**,但必须保留剩余字符串的任何和所有变音符号(如果有的话)**。
对于从StackOverflow上的英语字符串中删除第一个/开始字符串/字符有很多答案,但是在StackOverflow上没有找到这个问题的现有解决方案,可以保持阿拉伯字符串的原始形式。
如果原始字符串在处理之前被规范化(删除变音符号,tanween等),那么返回的剩余字符串将是规范化字符串的余额,而不是原始字符串的剩余部分。
假设以下原始字符串可以是以下任何形式(即相同的字符串但不同的变音符号):
1.“ا لسل ا م علي م ورحمة ا ل له"
2.“ا لس ل ا م علي م ورحمة ا ل له"
3.“ا لس ل ا م ع لي م ور حمة ا ل له"
4.“ا لس ل ا م ع ل ي م و ر ح م ة ا ل له"
现在,假设我们想要移除第一个/起始字符“السلام”,只有当字符串以这样的字符开头时(它确实这样做了),并返回剩余的“original”字符串及其原始变音符号。
当然,我们正在寻找没有变音符号的字符“السلام”,因为我们不知道原始字符串是如何用变音符号格式化的。
因此,在这种情况下,返回的每个字符串的剩余部分必须是:
1.“علي م ورحمة ال له"
2.“علي م ورحمة ال له"
3.“ع لي م ور حمة ال له"
4.“ع ل ي م و ر ح م ة ال له"
下面的代码适用于英语字符串(有许多其他解决方案),但不适用于阿拉伯语字符串,如上所述。
function removeStartWord(string,word) {
if (string.startsWith(word)) string=string.slice(word.length);
return string;
}
上面的代码使用了基于字符长度对从原始字符串中找到的起始字符进行切片的原理;这对于英语文本来说很好。
对于阿拉伯字符串,我们不知道原始字符串的变音符号的形式,因此我们在原始字符串中查找的字符串/字符的长度将是不同的和未知的。
编辑:添加了示例图像,以便更好地说明。
以下图像表提供了进一步的示例:
6条答案
按热度按时间avwztpqn1#
为了跟踪讨论,我添加了一个新的答案,请尝试!
qjp7pelc2#
我提出了以下可能的解决方案。
将以下溶液分成2部分;首先,函数
startsWithAr()
用于“部分地”模仿javascriptx 1 m1n1x方法,但是用于阿拉伯字符串。但是,它不会返回
'true'
或'false'
,而是返回源字符串开头的index after the characters we are looking for
(即在源字符串中找到的字符串的长度,包括它的Tashkeel(变音符号)(如果有的话),否则,如果在字符串的开头没有找到指定字符串的字符,则返回-1
。使用
startsWithAr()
函数,然后创建(在第二部分)一个函数,如果使用slice()
方法在源字符串的开头找到指定字符串的字符,则删除该字符串;removeStartString()
函数这种方法不仅允许保持源字符串的其余部分的Tashkeel(变音符号),而且还允许搜索和删除具有Tahmeez的字符串。
该函数忽略**源字符串和Look-For Search字符串中的Tashkeel(diacritics)和Tahmeez,并将在从源字符串的开头删除指定的起始字符后,完整地返回源字符串的剩余部分及其原始Tashkeel(diacritics)。
这样,我们就可以使用该函数处理阿拉伯语脚本中的所有Unicode,而不是将其限制在定义的范围内,因为任何语言的任何其他字符都被忽略。
我们也可以通过匹配“ه”和“ة”来轻松地改进它,这样我们就可以通过在2个
.replace()
行添加.replace(/[ة]/g,'ه')
来删除字符串“ال س ي دة”,即使它被写为“ال س ي ده”。我在下面列出了使用
startsWithAr()
函数和removeStartString()
函数的单独测试用例。如果需要,这两个功能可以组合成一个功能。
请根据需要改进;欢迎提出任何建议。
第一部分:startsWithAr()
第二部分:removeStartString()
rsl1atfo3#
使用 regex unicode escapes 可能已经足够好了,尽管JavaScript不支持像
\p{Arabic}
这样的 *unicode脚本 *。像
/^[\p{L}\p{M}]+\p{Z}+/gmu
和replace
这样的基于类别的模式已经完全满足了OP的要求……模式...
^[\p{L}\p{M}]+\p{Z}+
...读起来是这样的^
...从新行的开头开始...[ ... ]+
...在列表中查找指定字符类的一个字符...\p{L}
...任何语言的任何类型的字母,\p{M}
...或旨在与另一字符组合的字符(例如,重音符号、变音符号、封闭框等)\p{Z}+
任何类型的空白或不可见分隔符中的至少一个。编辑
因为现在很清楚OP真正想要的是什么,所以上面的方法仍然存在,只是通过利用
replacer
函数和基于Intl.Collator
对象的额外比较逻辑来提升到下一个级别,该对象考虑了阿拉伯语和基本字母的比较。通过提供(除了
'ar'
局部变量之外)一个具有 base sensitivity 的选项,可以最不严格地初始化collator。因此,当通过排序器的compare
方法比较两个相似(但不完全相等)的字符串时,例如:'السلام'
和'السَّلَامُ'
将被认为是相等的,尽管后者具有(很多)变音符号。证明/示例...
基于以上所说的…最终的解决方案
yzuktlbb4#
由于需求变化(d)和信息一片一片地进来,……
我也会从一张白纸开始。
组合的方法是对基于
Intl.Collator
的区域设置compare
进行匹配,而基于Unicode property escapes的正则表达式匹配任何阿拉伯语单词,而不管组合字符,如重音,变音等。如果要查找/匹配任何类型的字符串(这里是在新行的开头),则不能再使用。但是,任何试图简单地迭代字符串并逐字符比较两个字符串的方法都将失败。
示例代码比文字更能说明问题……让我们看看...
幸运的是,ECMAScript的国际化API
Intl
也可以在这里提供帮助。有Intl.Segmenter
,这将有助于将字符串分解为可比较的片段。对于OP的用例来说,在默认的granularity
级别'grapheme'
上执行它就足够了,这似乎等于 * 分割成locale可比字母 *...因此,最后一步是通过将上面介绍的
Intl.Segmenter
与现在已经熟悉的Intl.Collator
...mm5n2pyu5#
我看不出你的代码有什么问题,但这里有另一种方法:
6rqinv9w6#
我已经创建了一个npm包来解决这个问题,你所要做的就是
在你的代码中,你可以这样做:
如果你想确保文本只存在于字符串的开头你可以这样做
另外请记住,该软件包不会规范化标记字符串,因此在使用startsWith和remove方法之前,您可能需要删除其中的变音符号
包仓库**https://github.com/justgo97/arabic-utils**
如果你出于某种原因不想使用一个包,那么这是需要的代码
假设我们有这两个字符串
我们将需要一个函数来删除变音符号,因为我们将使用它来获得原始文本的 backbone ,这是我个人使用的,但您可以根据需要使用不同的方法
然后我们将需要一个函数来将原始字符串分割成一个字母数组,并带有相应的变音符号,这样我们就可以将它与我们从中剥离变音符号的字符串的长度相匹配
现在我们有了这些函数,我们可以创建removeFromStart函数
就这样