Using regex with javascript to money string transform - javascript

I have a money value as "R$ 2.200,00" where my thousand separators are . and my decimal separator is ,.
I would like um regex to transform this string into a valid MySQL decimal number.
Possible values:
"R$ 23.000,20", "23.000,30", "R$ 1300,20", "R$ 100", "161,43256"
The results would be:
"23000.20", "23000.30", "1300.20", "100", "161.43256"
My attempt is below, but it does not work. I would like to accept only numbers and dot(.) for the results.
const str = "R$ 2.200,000";
const res = str
.replace(/R$/gi, "")
.replace(/./gi, "")
.replace(/,/gi, ".");
console.log(res);

With optimisations this seems to be working:
const possible = [
"R$ 23.000,20",
"23.000,30",
"R$ 1300,20",
"R$ 100 ",
"161,43256",
"R$ -23.000,20",
"-23.000,30",
"R$ -1300,20",
"R$ -100",
"-161,43256"
]
const rx = /[^-\d,]+/g // Match everything except digits, comma, dot and negative
const parseNumber = num =>
num
.replace(rx, '') // Filter out non numeric entities
.replace(',', '.') // Replacing comma with dot
possible.forEach(num => {
console.log(num, '\t->\t', parseNumber(num))
})

this regEx replace/remove: (/[^\w\s]/gi) all special globaly signs ("$", ".", ","),
next one give the digit part (/\D/g)
and finally with string methods substring(,) place a ',' between the last two digits in the length of the string.
let input = "R$ 2.200,000";
let res = input.replace(/[^\w\s]/gi, '')
let str = res.replace(/\D/g,'');
let resStr = str.substring(0,str.length-2)+"."+str.substring(str.length-2);
console.log(resStr)

Edit: However this will not work if you have more than one thousand seperator, do not use it if you may have.
So, if you don't have to use regex, you can use replace function with strings too.
const str = "R$ 2.200,00";
const res = str
.replace('R$ ', "")
.replace('.', "")
.replace(',', ".")
console.log(res);
The code above will give you the format you want as a String. If you need Float, you can use parseFloat function.
console.log(parseFloat(res));
You can even use toFixed if you want absolute number of numbers after floating point
console.log(parseFloat(res).toFixed(5));

let input1 = "R$ 2.200,000";
let input2 = "23.000,30";
let input3 = "R$ 1300,20";
let input4 = "R$ 100";
let input5 = "161,43256";
const formatMoney = (inpStr) => {
let res = inpStr
res = res.replace(/[$R\s]/g, '');
let idx = res.indexOf('.')
res = res.replace(/,/, '.')
for (let i in res) {
if (res[i] === '.' && i !== i) {
res[i] = ','
}
}
return res
}
console.log(formatMoney(input1))
console.log(formatMoney(input2))
console.log(formatMoney(input3))
console.log(formatMoney(input4))
console.log(formatMoney(input5))

You could do that in two steps.
Step 1: remove characters
Substitute matches of the following regular expression with empty strings.
/(?:^R\$ +|[,.](?=.*[,.]))/gm
This will convert the strings
R$ 23.000,20
23.000,30
R$ 1300,20
R$ 100
161,43256
R$ 23.123.000,20
to
23000,20
23000,30
1300,20
100
161,43256
23123000,20
Javascript's regex engine performs the following steps.
(?: : begin a non-capture groups
^ : beginning of string
R\$ + : match 'R$' followed by 1+ spaces
| : or
[,.] : match ',' or '.'
(?= : begin positive lookahead
.* : match 0+ characters other than line terminators
[,.] : match ',' or '.'
) : end positive lookahead
) : end non-capture group
Step 2: convert comma, if present, to a period
Substitute matches of the following regular expression with a period.
/[,.]/gm
That would convert the above strings to the following.
23000.20
23000.30
1300.20
100
161.43256
23123000.20
Restart your engine!

Related

how to split string every 2 character

var alphabet = "FIN SLHOJVHEN GYKOHU";
I want to split it every 2 character so it would print
"I LOVE YOU "
I already try this but it didn't work
for (var i = 0 ; i \< alphabet.length ; i+=2 ){
alphabet.split(i)
correct me please
You can transform the string into an array, filter it and make it a string again.
let alphabet = "FIN SLHOJVHEN GYKOHU";
alphabet = [...alphabet].filter((_, i) => i%2).join("");
console.log(alphabet); //I LOVE YOU;
Also this one results in I LOVE YOU (regex101 demo).
// the string
let alphabet = 'FIN SLHOJVHEN GYKOHU';
// capture ^ start or chr, match latter chr
alphabet = alphabet.replace(/(^|.)./g, '$1');
console.log(alphabet);
Since the split function will split the given string by the delimiter you passed, it seems to me that you wish to first split the words (using empty space) contained in the encoded string and only then take only the characters at even positions to include in the decoded string.
This is a demo achieving that:
const encoded = "FIN SLHOJVHEN GYKOHU";
const words = encoded.split(' ');
let decoded = '';
words.forEach((word)=>{
for (let i=1;i<word.length;i+=2){
decoded += word[i];
}
decoded += ' ';
});
console.log(decoded);
Using a regex replacement approach we can try:
var alphabet = "FIN SLHOJVHEN GYKOHU";
var output = alphabet.replace(/[A-Z]([A-Z]|(?=\s))/g, "$1");
console.log(output);
Here is an explanation of the regex pattern:
[A-Z] match a single (odd) uppercase letter
( open capture
[A-Z] an uppercase letter
| OR
(?=\s) lookahead and find a space
)
In other words, we match an odd letter and then capture the next letter, unless that odd letter happen to be the last in the word. Then we replace with just the captured even letter, if available.
you already have different ways to do it, I'm adding one, so you'll get totally confused! hehe
This one is recursive:
we take your string alphabet
first 2 letters (every 2)
last one of this 2 characters string is stored in toPrint variable
delete the first 2 characters from alphabet
... loop till alphabet empty
Your toPrint has I Love You
Certainly not the fastest one, but nice.
let alphabet = "FIN SLHOJVHEN GYKOHU";
let toPrint = '';
do {
let temp = alphabet.slice(0, 2);
toPrint += temp[1];
alphabet = alphabet.slice(2, alphabet.length);
} while (alphabet !== '');
console.log(toPrint);
You can start your loop at 1 as you want every second character, and note that \< should be <
In the loop, i is the position of the character, so you would still have to get the character for that position and then assemble the resulting string.
var alphabet = "FIN SLHOJVHEN GYKOHU";
var result = "";
for (var i = 1; i < alphabet.length; i += 2) {
result += alphabet[i];
}
console.log(result);
If you want to take the spaces into account and only get the 2nd non whitespace character you might:
get the separate words by splitting on whitespace chars
remove the empty entries
join every second character to a string
join the parts from the initial split with a space
const alphabet = " FIN SLHOJVHEN GYKOHU ";
const result = alphabet
.split(/\s+/)
.filter(Boolean)
.map(s => s.split("").filter((s, i) => i % 2).join(""))
.join(" ");
console.log(result);
If you have a browser where a positive lookbehind for a regex is supported:
const alphabet = " FIN SLHOJVHEN GYKOHU ";
const result = alphabet
.split(/\s+/)
.filter(Boolean)
.map(s => s.match(/(?<=^(?:..)*.)./g).join(""))
.join(" ");
console.log(result);
var alphabet = "FIN SLHOJVHEN GYKOHU";
const arrayAlpha = alphabet.split('');
let stringToPrint = '';
for(let i=1; i<arrayAlpha.length; i+=2){
stringToPrint = stringToPrint + arrayAlpha[i]
}
console.log(stringToPrint)

How can I mask the digits in a alphanumeric string when the count of digits reaches 10?

I have an alphanumeric string, so I want to mask all the numbers in this string when the count of digits reaches 10. In this example, the digit count has reached the count of 10 two times irrespective of how many space, special character,s or digits are there
For ex:
string 1:- abc23 56 dfg %#34567fhgh0 1234567890 abc345
Output:- abc** ** dfg %#*****fhgh* ********** abc345
It ignores the characters and mask the number when the digit length reaches 10. I want to do this with regex. How can I do that?
You may use something like this:
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
}
This will count the number of digit matches. If there are 10 or more digits, it replaces each one with a '*' character. If you want to only replace the digits if the string contains at least one set of 10 consecutive digits, see the end of the answer.
Here's a complete example:
var arr = ['abc23 56 dfg %#34567fhgh0 1234567890 abc345', 'abc123def'];
for (var i = 0; i < arr.length; i++) {
let s = arr[i];
if ((s.match(/\d/g) || []).length >= 10) {
s = s.replace(/\d/g, '*');
arr[i] = s;
}
console.log(s);
}
Output:
abc** ** dfg %#*****fhgh* ********** abc***
abc123def
If you want the condition to be for 10 consecutive digits, use the following instead:
if (/\d{10}/g.test(s)) {
s = s.replace(/\d/g, '*');
}
You could split() the string into an array, check the length of the string, if it is over 10, then map the mask character where the number was using splice and its key along with Number and isNan.
var str = 'abc23 56 dfg %#34567fhgh0 1234567890'
var str2 = 'abc345'
var str3 = '%#34567fhg7'
var str4 = '1234567890'
const exchange = (str, cap) => {
// split the string and define array
const arr = str.split('')
// condtional to see if string.length is greater than cap
if (str.length > cap) {
// we have a string longer than cap, loop over the array, exclude
// empty spaces and check if value is a number using isNaN, if it is,
// we splice its value using the key with the mask character x
arr.map((char, k) => char !== ' ' ? Number.isNaN(Number(char)) ? null : arr.splice(k, 1, 'x') : null)
// return the value as a string by joining the array values together
return arr.join('')
} else {
// return the string as its length is not more than cap
return str
}
}
console.log(`${exchange(str, 10)}, length = ${str.length}`)
console.log(`${exchange(str2, 10)}, length = ${str2.length}`)
console.log(`${exchange(str3, 10)}, length = ${str3.length}`)
console.log(`${exchange(str4, 10)}, length = ${str4.length}`)

camelCase to kebab-case

I have a kebabize function which converts camelCase to kebab-case. I am sharing my code. Can it be more optimized? I know this problem can be solved using regex. But, I want to do it without using regex.
const kebabize = str => {
let subs = []
let char = ''
let j = 0
for( let i = 0; i < str.length; i++ ) {
char = str[i]
if(str[i] === char.toUpperCase()) {
subs.push(str.slice(j, i))
j = i
}
if(i == str.length - 1) {
subs.push(str.slice(j, str.length))
}
}
return subs.map(el => (el.charAt(0).toLowerCase() + el.substr(1, el.length))).join('-')
}
kebabize('myNameIsStack')
const kebabize = str => {
return str.split('').map((letter, idx) => {
return letter.toUpperCase() === letter
? `${idx !== 0 ? '-' : ''}${letter.toLowerCase()}`
: letter;
}).join('');
}
console.log(kebabize('myNameIsStack'));
console.log(kebabize('MyNameIsStack'));
You can just check every letter is if upperCase or not and replace it.
I have a one-liner similar to Marc's but with a simpler Regular Expression and ~20% faster according my benchmark (Chrome 89).
const kebabize = (str) => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? "-" : "") + $.toLowerCase())
const words = ['StackOverflow', 'camelCase', 'alllowercase', 'ALLCAPITALLETTERS', 'CustomXMLParser', 'APIFinder', 'JSONResponseData', 'Person20Address', 'UserAPI20Endpoint'];
console.log(words.map(kebabize));
[A-Z]+(?![a-z]) matches any consecutive capital letters, excluding any capitals followed by a lowercase (signifying the next word). Adding |[A-Z] then includes any single capital letters. It must be after the consecutive capital expression, otherwise the expression will match all capital letters individually and never match consecutives.
String.prototype.replace can take a replacer function. Here, it returns the lowercased matched capital(s) for each word, after prefixing a hyphen when the match offset is truthy (not zero - not the first character of the string).
I suspect Marc's solution is less performant than mine because by using replace to insert hyphens and lowercasing the whole string afterwards, it must iterate over the string more than once, and its expression also has more complex look aheads/behind constructs.
Benchmark
RegEx is faster!
Unlike what you might think, the RegEx way of doing this is actually significantly faster! See benchmark.
The function below supports converting both camelCase and PascalCase into kebab-case:
function toKebabCase(str) {
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}
Here is my solution:
Works with camelCase and PascalCase:
let words = ['StackOverflow', 'camelCase', 'alllowercase', 'ALLCAPITALLETTERS', 'CustomXMLParser', 'APIFinder', 'JSONResponseData', 'Person20Address', 'UserAPI20Endpoint'];
let result = words.map(w => w.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, '-$1').toLowerCase());
console.log(result);
/*
Returns:
[
"stack-overflow",
"camel-case",
"alllowercase",
"allcapitalletters",
"custom-xml-parser",
"api-finder",
"json-response-data",
"person20-address",
"user-api20-endpoint"
]
*/
Explanation:
Match any of the following regular expressions:
Find any capital letter, that is immediately preceeded by a small letter or a number, or
Find any capital letter, that is immediately preceeded by a capital letter or a number, that is immediately followed by a small letter
Replace the captured position with a dash ('-') followed by the captured capital letter
Finally, convert the whole string to lowercase.
I would use something like this.
function kebabize(string) {
// uppercase after a non-uppercase or uppercase before non-uppercase
const upper = /(?<!\p{Uppercase_Letter})\p{Uppercase_Letter}|\p{Uppercase_Letter}(?!\p{Uppercase_Letter})/gu;
return string.replace(upper, "-$&").replace(/^-/, "").toLowerCase();
}
const strings = ["myNameIsStack", "HTTPRequestData", "DataX", "Foo6HelloWorld9Bar", "Áb"];
const result = strings.map(kebabize);
console.log(result);
This snippet replaces all uppercase characters before or after a non-uppercase character with - followed by the uppercase. It then removes the - at the start of the string (if there is any) and downcases the whole string.
Simple solution for older browsers:
var str = 'someExampleString'
var i
function camelToKebab() {
var __str = arguments[0]
var __result = ''
for (i = 0; i < __str.length; i++) {
var x = __str[i]
if(x === x.toUpperCase()) {
__result += '-' + x.toLowerCase()
} else {
__result += x
}
}
return __result
}
console.log(str, '->', camelToKebab(str))
Here is the solution I came up with:
let resultDiv = document.querySelector(".result");
let camelCase = "thisIsCamelCase";
let kebabCase;
kebabCase = camelCase.split('').map(el=> {
const charCode = el.charCodeAt(0);
if(charCode>=65 && charCode<=90){
return "-" + el.toLowerCase()
}else{
return el;
}
})
return(kebabCase.join(''))

JavaScript: Add space between Char and Number with Regex

Hello I have a plate number BZ8345LK and want convert to BZ 8345 LK (adding space between char and number).
I tried with this Regex but not working, only space first char with number. Ex BZ 8345LK, the 'LK' keep not space with number.
var str = 'BZ8345LK';
str.replace(/[^0-9](?=[0-9])/g, '$& ');
# return BZ 8345LK, I want BZ 8345 LK
You can use this regex
[a-z](?=\d)|\d(?=[a-z])
[a-z](?=\d) - Match any alphabet followed by digit
| - Alternation same as logical OR
\d(?=[a-z]) - Any digit followed by alphabet
let str = 'BZ8345LK'
let op = str.replace(/[a-z](?=\d)|\d(?=[a-z])/gi, '$& ')
console.log(op)
You should alternate with the other possibility, that a number is followed by a non-number:
var str = 'BZ8345LK';
console.log(str.replace(/[^0-9](?=[0-9])|[0-9](?=[^0-9])/g, '$& '));
An anoher option is to use:
^[^\d]+|[\d]{4}
Search for any not numeric character [^\d] followed by 4 numeric [\d]{4} characters
const str = 'BZ8345LK'
let answer = str.replace(/^[^\d]+|[\d]{4}/gi, '$& ')
console.log(answer)
Try with this
var str = "BZ8345LK";
var result = str.replace(/([A-Z]+)(\d+)([A-Z]+)/, "$1 $2 $3");
console.log(result);

javascript - count spaces before first character of a string

What is the best way to count how many spaces before the fist character of a string?
str0 = 'nospaces even with other spaces still bring back zero';
str1 = ' onespace do not care about other spaces';
str2 = ' twospaces';
Use String.prototype.search
' foo'.search(/\S/); // 4, index of first non whitespace char
EDIT:
You can search for "Non whitespace characters, OR end of input" to avoid checking for -1.
' '.search(/\S|$/)
Using the following regex:
/^\s*/
in String.prototype.match() will result in an array with a single item, the length of which will tell you how many whitespace chars there were at the start of the string.
pttrn = /^\s*/;
str0 = 'nospaces';
len0 = str0.match(pttrn)[0].length;
str1 = ' onespace do not care about other spaces';
len1 = str1.match(pttrn)[0].length;
str2 = ' twospaces';
len2 = str2.match(pttrn)[0].length;
Remember that this will also match tab chars, each of which will count as one.
You could use trimLeft() as follows
myString.length - myString.trimLeft().length
Proof it works:
let myString = ' hello there '
let spacesAtStart = myString.length - myString.trimLeft().length
console.log(spacesAtStart)
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft
str0 = 'nospaces';
str1 = ' onespace do not care about other spaces';
str2 = ' twospaces';
arr_str0 = str0.match(/^[\s]*/g);
count1 = arr_str0[0].length;
console.log(count1);
arr_str1 = str1.match(/^[\s]*/g);
count2 = arr_str1[0].length;
console.log(count2);
arr_str2 = str2.match(/^[\s]*/g);
count3 = arr_str2[0].length;
console.log(count3);
Here:
I have used regular expression to count the number of spaces before the fist character of a string.
^ : start of string.
\s : for space
[ : beginning of character group
] : end of character group
str.match(/^\s*/)[0].length
str is the string.

Categories