Как преобразовать персидские и арабские числа внутри строки в английский, используя JavaScript?
Как я могу преобразовать персидские / арабские числа в английские числа с помощью простой функции?
arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"]
persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"]
Это та же схема, но кодовые страницы разные.
18 ответов
Используйте эту простую функцию для преобразования вашей строки
var
persianNumbers = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g],
arabicNumbers = [/٠/g, /١/g, /٢/g, /٣/g, /٤/g, /٥/g, /٦/g, /٧/g, /٨/g, /٩/g],
fixNumbers = function (str)
{
if(typeof str === 'string')
{
for(var i=0; i<10; i++)
{
str = str.replace(persianNumbers[i], i).replace(arabicNumbers[i], i);
}
}
return str;
};
Будьте осторожны, в этом коде кодовая страница персидских чисел отличается от арабских чисел.
пример
var mystr = 'Sample text ۱۱۱۵۱ and ٢٨٢٢';
mystr = fixNumbers(mystr);
Один список всех 6 возможных переводов между английскими, арабскими и персидскими цифрами.
const e2p = s => s.replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])
const e2a = s => s.replace(/\d/g, d => '٠١٢٣٤٥٦٧٨٩'[d])
const p2e = s => s.replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
const a2e = s => s.replace(/[٠-٩]/g, d => '٠١٢٣٤٥٦٧٨٩'.indexOf(d))
const p2a = s => s.replace(/[۰-۹]/g, d => '٠١٢٣٤٥٦٧٨٩'['۰۱۲۳۴۵۶۷۸۹'.indexOf(d)])
const a2p = s => s.replace(/[٠-٩]/g, d => '۰۱۲۳۴۵۶۷۸۹'['٠١٢٣٤٥٦٧٨٩'.indexOf(d)])
e2p("asdf1234") // asdf۱۲۳۴
e2a("asdf1234") // asdf١٢٣٤
p2e("asdf۱۲۳۴") // asdf1234
a2e("asdf١٢٣٤") // asdf1234
p2a("asdf۱۲۳۴") // asdf١٢٣٤
a2p("asdf١٢٣٤") // asdf۱۲۳۴
Объяснение:
(s => f(s))(x)
- это лямбда-функция, которая выполняется немедленно и будет равна f(x)s.replace(pattern, function)
ищет совпадения с шаблоном в s, для каждого совпадения m он заменяет m наfunction(m)
в строке./\d/g
это шаблон регулярного выражения,\d
означает цифру на английском языке,g
означает глобальный. Если вы не укажетеg
он будет соответствовать только первому вхождению, иначе он будет соответствовать всем вхождениям.- В этом случае для каждой английской цифры
d
в строке эта цифра будет заменена на'۰۱۲۳۴۵۶۷۸۹'[d]
таким образом, 3 будет заменен третьим индексом в этом списке ('۰۱۲۳۴۵۶۷۸۹'
) что есть '۳' /[۰-۹]/g
является эквивалентным регулярным выражением для персидских цифр, на этот раз мы не можем использовать тот же метод, прежде чем мы воспользовались тем фактом, что javascript динамически типизирован и что d автоматически преобразуется из строки (соответствие регулярного выражения) в число (индекс массива) (ты можешь сделать'1234'['1']
в javascript, который совпадает с'1234'[1]
)- но на этот раз мы не можем этого сделать, потому что
'1234'['۱']
является недействительным. поэтому мы используем трюк и используемindexOf
которая является функцией, которая сообщает нам индекс элемента в массиве (здесь символ в строке), поэтому'۰۱۲۳۴۵۶۷۸۹'.indexOf(۳)
даст нам3
потому как'۳'
это третий индекс в строке'۰۱۲۳۴۵۶۷۸۹'
Это простой способ сделать это:
function toEnglishDigits(string) {
// convert persian digits [۰۱۲۳۴۵۶۷۸۹]
var e = '۰'.charCodeAt(0);
string = string.replace(/[۰-۹]/g, function(t) {
return t.charCodeAt(0) - e;
});
// convert arabic indic digits [٠١٢٣٤٥٦٧٨٩]
e = '٠'.charCodeAt(0);
string = string.replace(/[٠-٩]/g, function(t) {
return t.charCodeAt(0) - e;
});
return string;
}
пример:
alert(toEnglishDigits("abc[0123456789][٠١٢٣٤٥٦٧٨٩][۰۱۲۳۴۵۶۷۸۹]"));
// expected result => abc[0123456789][0123456789][0123456789]
Самая высокопроизводительная (быстрая и точная) функция, которая может поддерживать как персидские, так и арабские цифры (цифровые символы Unicode):
Как это работает
Сначала с помощью replace() + набора символов RegEx в диапазоне арабских цифр Unicode
U+0660 - U+0669 = ٠ ... ۹
и персидская цифра Unicode
U+06F0 - U+06F9 = ۰ ... ۹
он обнаружит любой символ строки, который соответствует ему.
Затем, поскольку основные латинские цифры (ASCII) имеют одинаковые концы в Unicode
U+003
- U+003
=
0
-
9
, Так что если мы удалим их разницу в базе, конец может быть одинаковым.
Для этого мы можем использовать операцию побитового И (&amp;) между их Char-кодом, используя charCodeAt() , чтобы осталась одна и та же часть.
Объяснять:
// x86 (Base 10) --> Binary (Base 2)
'٤'.charCodeAt(0); // 1636 (Base 10)
'۴'.charCodeAt(0); // 1780 (Base 10)
(1636).toString(2); // 0000000000000000000001100110 0100 (Base 2)
(1780).toString(2); // 0000000000000000000001101111 0100 (Base 2)
(4).toString(2); // 0000000000000000000000000000 0100 (Base 2)
// We need a // 0000000000000000000000000000 1111 (Base 2)
// To And it, for keeping just the 1's
// 0xf = 15
(15).toString(2); // 0000000000000000000000000000 1111 (Base 2)
// So
(
1780 // 0000000000000000000001101111 0100 (Base 2)
& // AND (Operation)
15 // 0000000000000000000000000000 1111 (Base 2)
)
==
4 // 0000000000000000000000000000 0100 (Base 2)
// ---> true
// Also (1636 & 15) == 4 <--- true
Минимизированная версия (все браузеры):
function toEnDigit(s){return s.replace(/[\u0660-\u0669\u06f0-\u06f9]/g,function(a){return a.charCodeAt(0)&15})}
OneLiner (современные браузеры)
const toEnDigit=s=>s.replace(/[٠-٩۰-۹]/g,a=>a.charCodeAt(0)&15);
Лучший способ сделать это вернуть индекс числа в массиве:
String.prototype.toEnglishDigits = function () {
return this.replace(/[۰-۹]/g, function (w) {
var persian = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
return persian.indexOf(w);
});
};
Если строка может содержать как "арабские", так и "персидские" числа, то однострочное "заменить" может выполнить дзё следующим образом.
Арабские и персидские числа конвертируются в английские эквиваленты. Остальной текст остается без изменений.
Num= "۳٣۶٦۵any٥۵٤۶32٠۰"; // Output should be "33665any55453200"
Num = Num.replace(/[٠-٩]/g, d => "٠١٢٣٤٥٦٧٨٩".indexOf(d)).replace(/[۰-۹]/g, d => "۰۱۲۳۴۵۶۷۸۹".indexOf(d));
console.log(Num);
Коротко и просто!
"۰۱۲۳۴۵۶۷۸۹".replace(/([۰-۹])/g, function(token) { return String.fromCharCode(token.charCodeAt(0) - 1728); });
Преобразует любое персидское или арабское (или смешанное) число в " английские " числа ( индусско-арабские цифры)
var transformNumbers = (function(){
var numerals = {
persian : ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"],
arabic : ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"]
};
function fromEnglish(str, lang){
var i, len = str.length, result = "";
for( i = 0; i < len; i++ )
result += numerals[lang][str[i]];
return result;
}
return {
toNormal : function(str){
var num, i, len = str.length, result = "";
for( i = 0; i < len; i++ ){
num = numerals["persian"].indexOf(str[i]);
num = num != -1 ? num : numerals["arabic"].indexOf(str[i]);
if( num == -1 ) num = str[i];
result += num;
}
return result;
},
toPersian : function(str, lang){
return fromEnglish(str, "persian");
},
toArabic : function(str){
return fromEnglish(str, "arabic");
}
}
})();
//////// ON INPUT EVENT //////////////
document.querySelectorAll('input')[0].addEventListener('input', onInput_Normal);
document.querySelectorAll('input')[1].addEventListener('input', onInput_Arabic);
function onInput_Arabic(){
var _n = transformNumbers.toArabic(this.value);
console.clear();
console.log( _n )
}
function onInput_Normal(){
var _n = transformNumbers.toNormal(this.value);
console.clear();
console.log( _n )
}
input{ width:90%; margin-bottom:1em; font-size:1.5em; padding:5px; }
<input placeholder="write in Arabic numerals">
<input placeholder="write in normal numerals">
Вы можете сделать что-то вроде этого, использующее индекс числа в строке для преобразования:
// Returns -1 if `fromNum` is not a numeric character
function convertNumber(fromNum) {
var persianNums = '۰١۲۳۴۵۶۷۸۹';
return persianNums.indexOf(fromNum);
}
var testNum = '۴';
alert("number is: " + convertNumber(testNum));
Или карту, используя объект как это:
// Returns -1 if `fromNum` is not a numeric character
function convertNumber(fromNum) {
var result;
var arabicMap = {
'٩': 9,
'٨': 8,
'٧': 7,
'٦': 6,
'٥': 5,
'٤': 4,
'٣': 3,
'٢': 2,
'١': 1,
'٠': 0
};
result = arabicMap[fromNum];
if (result === undefined) {
result = -1;
}
return result;
}
var testNum = '٤';
alert("number is: " + convertNumber(testNum));
function toEnglishDigits(str) {
const persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"]
const arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"]
const englishNumbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
return str.split("").map(c => englishNumbers[persianNumbers.indexOf(c)] ||
englishNumbers[arabicNumbers.indexOf(c)] || c).join("")
}
toEnglishDigits("۶٦۵any٥32") // "665any532"
На основе user7514010 для преобразования персидских и арабских чисел в английские числа с сохранением всех остальных символов без изменений выглядит следующим образом:
const toEnDigit=n=>n.replace(/[٠-٩۰-۹]/g,n=>15&n.charCodeAt(0));
Вы можете использовать новую библиотеку Persian-tools, которая представляет собой отличную библиотеку javascript для работы с персидскими словами и числами. Вот образец задачи, которую вы просили:
import { digitsArToFa, digitsArToEn, digitsEnToFa, digitsFaToEn } from "persian-tools2";
digitsArToFa("٠١٢٣٤٥٦٧٨٩"); // "۰۱۲۳۴۵۶۷۸۹"
digitsArToEn("٠١٢٣٤٥٦٧٨٩"); // "0123456789"
digitsEnToFa("123۴۵۶"); // "۱۲۳۴۵۶"
digitsFaToEn("۰۱۲۳۴۵۶۷۸۹"); // "0123456789"
Вы также можете найти много других полезных функций на странице репозитория библиотеки.
function persianToEnglishNumbers(persianNumber) {
const persianDigits = '۰۱۲۳۴۵۶۷۸۹';
const englishDigits = '0123456789';
for (let i = 0; i < 10; i++) {
persianNumber = persianNumber.replace(new RegExp(persianDigits[i], 'g'), englishDigits[i]);
}
return persianNumber;
}
Если у вас есть числовая строка (строка, представляющая число), вот функция paserNumber , которая преобразует ее в фактический объект JS Number :
function parseNumber(numberText: string) {
return Number(
// Convert Persian (and Arabic) digits to Latin digits
normalizeDigits(numberText)
// Convert Persian/Arabic decimal separator to English decimal separator (dot)
.replace(/٫/g, ".")
// Remove other characters such as thousands separators
.replace(/[^\d.]/g, "")
);
}
const persianDigitsRegex = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g];
const arabicDigitsRegex = [/٠/g, /١/g, /٢/g, /٣/g, /٤/g, /٥/g, /٦/g, /٧/g, /٨/g, /٩/g];
function normalizeDigits(text: string) {
for (let i = 0; i < 10; i++) {
text = text
.replace(persianDigitsRegex[i], i.toString())
.replace(arabicDigitsRegex[i], i.toString());
}
return text;
}
Обратите внимание, что функция синтаксического анализа довольно щадящая, а числовая строка может быть комбинацией персидских/арабских/латинских цифр и разделителей.
После получения числа вы можете отформатировать его, как хотите, с помощью функции Number.toLocaleString :
let numberString = "۱۲۳۴.5678";
let number = parseNumber(numberString);
val formatted1 = number.toLocaleString("fa"); // OR "fa-IR" for IRAN
val formatted2 = number.toLocaleString("en"); // OR "en-US" for USA
val formatted3 = number.toLocaleString("ar-EG"); // OR "ar" which uses western numerals
Для получения дополнительной информации о форматировании чисел обратитесь к этому ответу .
Вы можете использоватьtoLocaleString()
.
'1234567890'.toLocaleString('fa-IR')
// ۱۲۳٬۴۵۶٬۷۸۹٬۰
Чтобы удалить разделитель из чисел, добавьте эту опцию:
'1234567890'.toLocaleString('fa-IR', { useGrouping: false })
// ۱۲۳۴۵۶۷۸۹۰
Для решения React с использованием машинописного текста это может быть полезно:
// https://gist.github.com/alieslamifard/364862613408a98139da3cab40abbeb9
import React, { InputHTMLAttributes, useEffect, useRef } from 'react';
// Persian/Arabic To English Digit
const f2e = (event) => {
event.target.value = event.target.value
.replace(/[٠-٩]/g, (d) => '٠١٢٣٤٥٦٧٨٩'.indexOf(d))
.replace(/[۰-۹]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d));
return event;
};
const useForwardedRef = (ref) => {
const innerRef = useRef(null);
useEffect(() => {
if (!ref) return;
if (typeof ref === 'function') {
ref(innerRef.current);
} else {
ref.current = innerRef.current;
}
}, [ref]);
return innerRef;
};
const Input = React.forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>(
(props, ref) => {
const innerRef = useForwardedRef(ref);
useEffect(() => {
innerRef.current?.addEventListener('keyup', f2e);
return () => {
innerRef.current?.removeEventListener('keyup', f2e);
};
}, [innerRef]);
return <input {...props} ref={innerRef} />;
},
);
export default Input;
Просто используйте
Input
вместо родного
input
в твоей форме :)
Я использую вот это:
AanyVariable = AanyVariable.replace(/([۰-۹])/g, (token) =>
String.fromCharCode(token.charCodeAt(0) - 1728)
);