쉼표로 구분 된 문자열을 숫자로 구문 분석하려면 어떻게해야합니까?


104

나는 2,299.00문자열로 가지고 있으며 그것을 숫자로 구문 분석하려고합니다. 를 사용해 보았습니다. parseFloat결과는 2입니다. 쉼표가 문제인 것 같지만이 문제를 어떻게 올바르게 해결할 수 있습니까? 쉼표 만 제거 하시겠습니까?

var x = parseFloat("2,299.00")
alert(x);

답변:


121

예 쉼표를 제거하십시오.

parseFloat(yournumber.replace(/,/g, ''));

7
예,하지만 이제 소수점 자리가 없어졌습니다. 예를 들어 2300.00은 2300이됩니다.
user1540714 jul.

@ user1540714 그 이유는 문자열이 아닌 부동 소수점이기 때문입니다. 그런 다음 출력해야하는 경우 항상 소수점 2 자리를 표시하도록 형식을 지정해야합니다.
존 테일러

피할 수 있습니까? Ill try toFixed
user1540714 jul.

38
대신 다음을 사용하여 모든 쉼표를 캡처하는 것이 좋습니다. .replace(/,/g, '') 이 정규식은 전역 g을 사용하여 모두를 대체합니다.
gdibble

32
이 답변이 왜 그렇게 많은 찬성 투표를 받고 올바른 것으로 선택되었는지 모르겠습니다. 두 가지 심각한 문제가 있습니다. 1. 여러 쉼표가있는 숫자를 처리 할 수 ​​없습니다 (예 : parseFloat("2,000,000.00".replace(',',''))return 2000및 2. ,소수점 이하 자릿수가있는 세계 여러 지역에서 실패 ) (예 : parseFloat("2.000.000,00".replace(',',''))return). 2아래의 내 대답에서 전 세계 모든 곳에서 작동하는 것을 참조하십시오.
데이비드 마이스터

113

쉼표를 제거하는 것은 다른 사람들이 주석에서 언급했듯이 많은 로케일에서 쉼표를 사용하여 다른 의미 (예 : 소수점 자리)를 사용하므로 잠재적으로 위험합니다.

나는 당신이 당신의 끈을 어디서 얻었는지 모르지만 세계의 어떤 곳에서 "2,299.00"=2.299

Intl객체는이 문제를 해결하는 좋은 방법이 될 수 있지만 어떻게 든 Intl.NumberFormat.format()API 만으로 사양을 제공하고 parse대응 항목은 없습니다.

문화적 숫자 문자가있는 문자열을 i18n 정상적인 방식으로 시스템에서 인식 할 수있는 숫자로 구문 분석하는 유일한 방법은 CLDR 데이터를 활용하는 라이브러리를 사용하여 숫자 문자열 http : //cldr.unicode 를 형식화하는 모든 가능한 방법을 커버하는 것입니다 . org /

지금까지 내가 본 두 가지 최고의 JS 옵션 :


4
아직 아무도이 답변을 찬성하지 않았다고 믿을 수 없습니다.이 페이지의 유일한 실제 답변입니다!
evilkos

9
Intl에 파싱 대응자가 있어야한다는 데 완전히 동의합니다. 사람들이 이것을 필요로 할 것이 분명해 보입니다.
carlossless

이것이이를 수행하는 유일한 체계적인 방법입니다. 하나의 정규식으로 모든 접근 방식으로 이것을 달성 할 수 없습니다. 쉼표와 마침표는 언어마다 다른 의미를 갖습니다.
Wildhammer

38

최신 브라우저에서는 내장 된 Intl.NumberFormat 을 사용하여 브라우저의 숫자 형식을 감지하고 일치하도록 입력을 정규화 할 수 있습니다.

function parseNumber(value, locale = navigator.language) {
  const example = Intl.NumberFormat(locale).format('1.1');
  const cleanPattern = new RegExp(`[^-+0-9${ example.charAt( 1 ) }]`, 'g');
  const cleaned = value.replace(cleanPattern, '');
  const normalized = cleaned.replace(example.charAt(1), '.');

  return parseFloat(normalized);
}

const corpus = {
  '1.123': {
    expected: 1.123,
    locale: 'en-US'
  },
  '1,123': {
    expected: 1123,
    locale: 'en-US'
  },
  '2.123': {
    expected: 2123,
    locale: 'fr-FR'
  },
  '2,123': {
    expected: 2.123,
    locale: 'fr-FR'
  },
}


for (const candidate in corpus) {
  const {
    locale,
    expected
  } = corpus[candidate];
  const parsed = parseNumber(candidate, locale);

  console.log(`${ candidate } in ${ corpus[ candidate ].locale } == ${ expected }? ${ parsed === expected }`);
}

분명히 일부 최적화 및 캐싱의 여지가 있지만 이것은 모든 언어에서 안정적으로 작동합니다.


왜 이것이 많은 찬성표를 얻지 못했습니까! 국제 형식의 INPUT에 대한 가장 우아한 솔루션입니다! 감사합니다!!
kpollock

프랑스 통화 : 231 123 413,12
stackdave

26

숫자, 소수점 또는 빼기 기호 ( -) 가 아닌 것은 제거하십시오 .

var str = "2,299.00";
str = str.replace(/[^\d\.\-]/g, ""); // You might also include + if you want them to be able to type it
var num = parseFloat(str);

업데이트 된 바이올린

과학적 표기법의 숫자에는 작동하지 않습니다. 당신이 그것을 원하는 경우, 변경 replace추가 라인을 e, E그리고 +허용되는 문자 목록에 :

str = str.replace(/[^\d\.\-eE+]/g, "");

4
과학적 표기법의 음수 또는 숫자에는 작동하지 않습니다.
Aadit M Shah

1
str = str.replace(/(\d+),(?=\d{3}(\D|$))/g, "$1"); 이것은 내가 사용할 것이지만 정규식에서는 완전히 쓸모가 없으며 다른 SO 스레드에서 잠시 동안 찾은 것입니다.
존 테일러

@JonTaylor : 여기서 목표 는 숫자의 유효성확인 하는 것이 아니라 작동하도록 만드는 것이 parseFloat었습니다. :-)
TJ Crowder

내가 아는 한 내 것이하는 일입니다. 나는 이것을 사용하여 1,234,567 등을 1234567로 변환합니다. 내가 말했듯이 정규식에서는 완전히 쓸모가 없어서 실제로 무엇을하는지 말할 수 없었습니다.
Jon Taylor

1
"-"빼기 기호를 제거하는 것은 좋지 않습니다.-완전히 다른 숫자를 얻습니다. 또한 이기종 형식을 구문 분석하는 경우 "7.500"! == "7,500"
Serge

14

일반적으로 숫자 값에 대한 자유 텍스트 입력을 허용하지 않는 입력 필드를 사용하는 것을 고려해야합니다. 그러나 입력 형식을 추측해야하는 경우가있을 수 있습니다. 예를 들어 독일에서 1.234,56은 미국에서 1,234.56을 의미합니다. 쉼표를 십진수로 사용하는 국가 목록은 https://salesforce.stackexchange.com/a/21404 를 참조 하십시오 .

다음 함수를 사용하여 가장 잘 추측하고 숫자가 아닌 모든 문자를 제거합니다.

function parseNumber(strg) {
    var strg = strg || "";
    var decimal = '.';
    strg = strg.replace(/[^0-9$.,]/g, '');
    if(strg.indexOf(',') > strg.indexOf('.')) decimal = ',';
    if((strg.match(new RegExp("\\" + decimal,"g")) || []).length > 1) decimal="";
    if (decimal != "" && (strg.length - strg.indexOf(decimal) - 1 == 3) && strg.indexOf("0" + decimal)!==0) decimal = "";
    strg = strg.replace(new RegExp("[^0-9$" + decimal + "]","g"), "");
    strg = strg.replace(',', '.');
    return parseFloat(strg);
}   

여기에서 시도하십시오 : https://plnkr.co/edit/9p5Y6H?p=preview

예 :

1.234,56  => 1234.56
1,234.56USD => 1234.56
1,234,567 => 1234567
1.234.567 => 1234567
1,234.567 => 1234.567
1.234 => 1234 // might be wrong - best guess
1,234 => 1234 // might be wrong - best guess
1.2345 => 1.2345
0,123 => 0.123

이 함수에는 한 가지 약점이 있습니다. 1,123 또는 1.123이있는 경우 형식을 추측 할 수 없습니다. 로캘 형식에 따라 둘 다 쉼표 또는 천 단위 구분 기호 일 수 있기 때문입니다. 이 특별한 경우 함수는 구분 기호를 천 단위 구분 기호로 처리하고 1123을 반환합니다.


분명히 영어 형식 인 1,111.11과 같은 숫자에서는 실패하지만 111111을 반환합니다
Mr. Goferito

감사합니다, 고 페리 토 씨-죄송합니다-기능을 수정했습니다.
Gerfried

예를 들어 프랑스어 로케일에서 "0,124"라는 아주 작은 숫자의 경우에도 실패 할 수 있습니다.
폴 알렉산더

와우, 좋아요! 이것은 거의 정확히 내가 찾던 것입니다. 3,00 €또한 3.00으로 대체되었습니다. 그냥 참고 3,001로 포맷 3001. 이를 방지하려면 입력에 항상 소수점 기호가 있어야합니다. 예를 들어 3,001.00€ 3,001.00올바르게 변환됩니다. 또한 jsfiddle을 업데이트하십시오. 0,124여전히 124로 변환됩니다
Arnis Juraga

잘 했어 친구 나는 정답이 될 가치가 있다고 생각합니다
Waheed

5

toLocaleString이 포함되어 있지만 구문 분석 방법이 없다는 것은 당혹 스럽습니다 . 적어도 toLocaleString인수가없는 은 IE6 +에서 잘 지원됩니다.

A의 국제화의 솔루션, 나는이 함께했다 :

먼저 사용자의 로케일 소수 구분 기호를 감지하십시오.

var decimalSeparator = 1.1;
decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2);

그런 다음 문자열에 소수점 구분 기호가 두 개 이상 있으면 숫자를 정규화합니다.

var pattern = "([" + decimalSeparator + "])(?=.*\\1)";separator
var formatted = valor.replace(new RegExp(pattern, "g"), "");

마지막으로 숫자 또는 소수 구분 기호가 아닌 것은 제거하십시오.

formatted = formatted.replace(new RegExp("[^0-9" + decimalSeparator + "]", "g"), '');
return Number(formatted.replace(decimalSeparator, "."));

5

이것은 parseFloat함수를 둘러싼 단순하고 눈에 잘 띄지 않는 래퍼 입니다.

function parseLocaleNumber(str) {
  // Detect the user's locale decimal separator:
  var decimalSeparator = (1.1).toLocaleString().substring(1, 2);
  // Detect the user's locale thousand separator:
  var thousandSeparator = (1000).toLocaleString().substring(1, 2);
  // In case there are locales that don't use a thousand separator
  if (thousandSeparator.match(/\d/))
    thousandSeparator = '';

  str = str
    .replace(new RegExp(thousandSeparator, 'g'), '')
    .replace(new RegExp(decimalSeparator), '.')

  return parseFloat(str);
}

2

David Meister가 게시 한 문제를 피하고 소수점 이하 자릿수에 대해 확신하는 경우 모든 점과 쉼표를 대체하고 100으로 나눌 수 있습니다. 예 :

var value = "2,299.00";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/100;

또는 소수점 3 자리가있는 경우

var value = "2,299.001";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/1000;

parseInt, parseFloat 또는 Number를 사용하고 싶은지는 당신에게 달려 있습니다. 또한 소수 자릿수를 유지하려면 .toFixed (...) 함수를 사용할 수 있습니다.


1

이 모든 대답은 수백만 개가 있으면 실패합니다.

3,456,789는 replace 메서드를 사용하여 3456을 반환합니다.

단순히 쉼표를 제거하는 가장 정답은 다음과 같습니다.

var number = '3,456,789.12';
number.split(',').join('');
/* number now equips 3456789.12 */
parseFloat(number);

또는 단순히 작성되었습니다.

number = parseFloat(number.split(',').join(''));

물론 American은 점이 아닌 쉼표를 사용합니다. 두 가지를 모두 다루기 위해 괴물을 만들려고하는 것은 어리석은 일입니다.
케이스

2
그러나 그러한 "괴물"은 이미 유니 코드가 제공하는 것의 일부로 존재합니다 (내 대답 참조). 해외 고객과 함께 회사를 운영한다면 이것에 대해 덜 어리석은 느낌이들 것이라고 확신합니다.
데이비드 마이스터

1

이것은 어떤 로케일의 숫자를 일반 숫자로 변환합니다. 소수점에서도 작동합니다.

function numberFromLocaleString(stringValue, locale){
    var parts = Number(1111.11).toLocaleString(locale).replace(/\d+/g,'').split('');
    if (stringValue === null)
        return null;
    if (parts.length==1) {
        parts.unshift('');
    }   
    return Number(String(stringValue).replace(new RegExp(parts[0].replace(/\s/g,' '),'g'), '').replace(parts[1],"."));
}
//Use default browser locale
numberFromLocaleString("1,223,333.567") //1223333.567

//Use specific locale
numberFromLocaleString("1 223 333,567", "ru") //1223333.567

1

이 기능을 사용하면 같은 여러 형식의 값을 포맷 할 수 1.234,561,234.56, 심지어와 같은 오류 1.234.561,234,56

/**
 * @param {string} value: value to convert
 * @param {bool} coerce: force float return or NaN
 */
function parseFloatFromString(value, coerce) {
    value = String(value).trim();

    if ('' === value) {
        return value;
    }

    // check if the string can be converted to float as-is
    var parsed = parseFloat(value);
    if (String(parsed) === value) {
        return fixDecimals(parsed, 2);
    }

    // replace arabic numbers by latin
    value = value
    // arabic
    .replace(/[\u0660-\u0669]/g, function(d) {
        return d.charCodeAt(0) - 1632;
    })

    // persian
    .replace(/[\u06F0-\u06F9]/g, function(d) {
        return d.charCodeAt(0) - 1776;
    });

    // remove all non-digit characters
    var split = value.split(/[^\dE-]+/);

    if (1 === split.length) {
        // there's no decimal part
        return fixDecimals(parseFloat(value), 2);
    }

    for (var i = 0; i < split.length; i++) {
        if ('' === split[i]) {
            return coerce ? fixDecimals(parseFloat(0), 2) : NaN;
        }
    }

    // use the last part as decimal
    var decimal = split.pop();

    // reconstruct the number using dot as decimal separator
    return fixDecimals(parseFloat(split.join('') +  '.' + decimal), 2);
}

function fixDecimals(num, precision) {
    return (Math.floor(num * 100) / 100).toFixed(precision);
}
parseFloatFromString('1.234,56')
"1234.56"
parseFloatFromString('1,234.56')
"1234.56"
parseFloatFromString('1.234.56')
"1234.56"
parseFloatFromString('1,234,56')
"1234.56"

0

l10n 대답을 원한다면 이렇게하십시오. 예제는 통화를 사용하지만 필요하지 않습니다. 이전 브라우저를 지원해야하는 경우 Intl 라이브러리를 폴리 필해야합니다.

var value = "2,299.00";
var currencyId = "USD";
var nf = new Intl.NumberFormat(undefined, {style:'currency', currency: currencyId, minimumFractionDigits: 2});

value = nf.format(value.replace(/,/g, ""));

9
일부 로케일 (예 : DE)의 경우 쉼표가 소수점이기 때문에 이것은 실제로 l10n 대답이 아닙니다.
Andreas

또한 플래그 와 함께 replace()사용하지 않을 때 첫 번째 일치 만 대체합니다 . RegExp'g'
binki

@binki 감사합니다. 결정된.
Tony Topper

@Andreas 이것은 l10n 대답입니다. 다른 통화를 원하면 currencyId 값을 해당 국가 currencyId로 변경하면됩니다.
Tony Topper

1
@TonyTopper 이것은 ,일부 로케일에서 쉼표 구분자에있는 천 단위 구분 기호에 대한 대체가 하드 코딩된다는 사실을 변경하지 않습니다
Andreas

0

쉼표를 빈 문자열로 바꿉니다.

var x = parseFloat("2,299.00".replace(",",""))
alert(x);


이것은 안전하지 않습니다. 다른 답변에서 언급했듯이 세계의 많은 부분에서 쉼표는 소수점을 나타냅니다.
데이비드 마이스터

1
또한이 방법은 첫 번째 쉼표 만 대체하므로 2,299,000.00에서는 작동하지 않습니다
wizulus

0

지원할 작은 로케일 세트가있는 경우 몇 가지 간단한 규칙을 하드 코딩하는 것이 좋습니다.

function parseNumber(str, locale) {
  let radix = ',';
  if (locale.match(/(en|th)([-_].+)?/)) {
    radix = '.';
  }
  return Number(str
    .replace(new RegExp('[^\\d\\' + radix + ']', 'g'), '')
    .replace(radix, '.'));
}

0
const parseLocaleNumber = strNum => {
    const decSep = (1.1).toLocaleString().substring(1, 2);
    const formatted = strNum
        .replace(new RegExp(`([${decSep}])(?=.*\\1)`, 'g'), '')
        .replace(new RegExp(`[^0-9${decSep}]`, 'g'), '');
    return Number(formatted.replace(decSep, '.'));
};

0
Number("2,299.00".split(',').join(''));   // 2299

split 함수는 ","를 구분 기호로 사용하여 문자열을 배열로 분할하고 배열을 반환합니다.
join 함수는 split 함수에서 반환 된 배열의 요소를 결합합니다.
Number () 함수는 결합 된 문자열을 숫자로 변환합니다.


해결책이 무엇이며 어떻게 문제를 해결하는지에 대해 좀 더 자세히 설명해주십시오.
Tariq
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.