72

如何使用简单的功能将波斯/阿拉伯数字转换为英文数字?

arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"]
persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"]

它是相同的架构,但代码页不同。

4

14 回答 14

73

使用这个简单的函数来转换你的字符串

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);

参考

于 2015-07-15T19:40:56.553 回答
65

英语、阿拉伯语和波斯语数字之间所有 6 种可能翻译的Oneliner 。

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)是一个立即执行的 lambda 函数,将等于 f(x)
  • s.replace(pattern, function)在 s 中查找模式的匹配项,对于每个匹配项 m,它将替换function(m)字符串中的 m。
  • /\d/g是一种正则表达式模式,\d在英语中表示数字,g表示全球。如果你不指定g它只会匹配第一次出现,否则它将匹配所有出现。
  • 在这种情况下,对于字符串中的每个英文数字d,​​该数字将被替换为'۰۱۲۳۴۵۶۷۸۹'[d]so,3 将被替换为 list( '۰۱۲۳۴۵۶۷۸۹') 中的第三个索引,即“3”
  • /[۰-۹]/g是波斯数字的等效正则表达式 这次我们不能使用相同的方法,在我们利用 javascript 是动态类型的并且 d 自动从字符串(正则表达式匹配)转换为数字(数组索引)之前(你可以'1234'['1']在 javascript 中做这与'1234'[1]
  • 但是这次我们不能这样做,因为'1234'['۱']它是无效的。所以我们在这里使用一个技巧并使用indexOfwhich 是一个函数,它告诉我们数组中元素的索引(这里是字符串中的字符)所以,'۰۱۲۳۴۵۶۷۸۹'.indexOf(۳)会给我们3因为'۳'是字符串中的第三个索引'۰۱۲۳۴۵۶۷۸۹'
于 2019-09-29T16:16:19.843 回答
17

这是一种简单的方法:

function toEnglishDigits(str) {

    // convert persian digits [۰۱۲۳۴۵۶۷۸۹]
    var e = '۰'.charCodeAt(0);
    str = str.replace(/[۰-۹]/g, function(t) {
        return t.charCodeAt(0) - e;
    });

    // convert arabic indic digits [٠١٢٣٤٥٦٧٨٩]
    e = '٠'.charCodeAt(0);
    str = str.replace(/[٠-٩]/g, function(t) {
        return t.charCodeAt(0) - e;
    });
    return str;
}

一个例子:

console.log(toEnglishDigits("abc[0123456789][٠١٢٣٤٥٦٧٨٩][۰۱۲۳۴۵۶۷۸۹]"));
// expected result => abc[0123456789][0123456789][0123456789]
于 2018-06-30T08:27:07.303 回答
13

在数组中返回数字索引的最佳方法:

String.prototype.toEnglishDigits = function () {
    return this.replace(/[۰-۹]/g, function (chr) {
        var persian = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
        return persian.indexOf(chr);
    });
};
于 2018-07-03T06:51:40.443 回答
9

简短而容易!

"۰۱۲۳۴۵۶۷۸۹".replace(/([۰-۹])/g, function(token) { return String.fromCharCode(token.charCodeAt(0) - 1728); });

或者以更现代的方式

"۰۱۲۳۴۵۶۷۸۹".replace(/([۰-۹])/g, token => String.fromCharCode(token.charCodeAt(0) - 1728));
于 2019-06-05T21:05:52.363 回答
8

如果字符串可能同时包含阿拉伯”和“波斯”数字,那么单行“替换”可以完成如下工作。

阿拉伯文和波斯文数字转换为英文等值。其他文字保持不变。

Num= "۳٣۶٦۵any٥۵٤۶32٠۰";     // Output should be "33665any55453200"

Num = Num.replace(/[٠-٩]/g, d => "٠١٢٣٤٥٦٧٨٩".indexOf(d)).replace(/[۰-۹]/g, d => "۰۱۲۳۴۵۶۷۸۹".indexOf(d));

console.log(Num);

于 2020-07-28T12:13:40.233 回答
6

你可以做这样的事情,使用字符串中数字的索引来进行转换:

// 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));

于 2015-07-15T20:03:23.157 回答
6

将任何波斯阿拉伯(或混合)数字转换为“英语”数字(印度教阿拉伯数字

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">

于 2018-05-14T10:38:40.707 回答
4
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"
于 2020-07-26T13:58:31.460 回答
3

可以同时支持波斯/阿拉伯数字(Unicode 数字字符)的最高性能(快速和准确)函数是:

function toEnDigit(s) {
    return s.replace(/[\u0660-\u0669\u06f0-\u06f9]/g,    // Detect all Persian/Arabic Digit in range of their Unicode with a global RegEx character set
        function(a) { return a.charCodeAt(0) & 0xf }     // Remove the Unicode base(2) range that not match
    )
}

sample='English: 0123456789 - Persian: ۰۱۲۳۴۵۶۷۸۹ - Arabic: ٠١٢٣٤٥٦٧٨٩';
     // English: 0123456789 - Persian: 0123456789 - Arabic: 0123456789

console.log( toEnDigit(sample) );

它是如何工作的

首先,通过在阿拉伯数字 Unicode波斯数字 Unicode范围内使用replace() + RegEx 字符集,它将检测与它匹配的字符串中的任何字符。 U+0660 - U+0669 = ٠ ... ۹ U+06F0 - U+06F9 = ۰ ... ۹

然后因为基本拉丁数字(ASCII)在 Unicode 中具有相同的结尾,所以如果我们消除它们在基数中的差异,则结尾可以相同。 为此,我们可以通过使用charCodeAt()在它们的字符代码之间使用按位与 (&)操作来保持相同的部分。U+0030 - U+0039=0-9

解释:

// 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);
于 2022-01-08T18:58:28.007 回答
2

您可以使用新的Persian-tools库,这是一个很棒的 JavaScript 库来处理波斯语单词和数字。这是您要求的任务的示例:

import { digitsArToFa, digitsArToEn, digitsEnToFa, digitsFaToEn } from "persian-tools2";

digitsArToFa("٠١٢٣٤٥٦٧٨٩"); // "۰۱۲۳۴۵۶۷۸۹"
digitsArToEn("٠١٢٣٤٥٦٧٨٩"); // "0123456789"
digitsEnToFa("123۴۵۶"); // "۱۲۳۴۵۶"
digitsFaToEn("۰۱۲۳۴۵۶۷۸۹"); // "0123456789"

您还可以在库的存储库页面上找到许多其他有用的功能。

于 2021-01-03T05:04:10.223 回答
0

对于使用 typescript 的 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:)

于 2021-04-26T12:17:51.637 回答
0

const convertToPersianDigits = (number) => number.toLocaleString('fa-IR')

convertToPersianDigits(100000)    //۱۰۰٬۰۰۰

于 2021-07-24T07:48:51.920 回答
0

如果您手头有数字字符串(表示数字的字符串),这里有一个名为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

有关格式化数字的更多信息,请参阅此答案

于 2021-12-24T14:36:55.120 回答