Formatting negative numbers with regex - javascript

I need to format my numbers and I am using regex /(?=(?!^)(?:\d{3})+$)/g, to replace and insert , where it is necessary. But currently I have an issue with negative {3} 000 numbers, so comma is added after minus.
What am I doing wrong?
'-200'.replace(/(?=(?!^)(?:\d{3})+$)/g, ',')
returns: -,200
correct: -200
'-2000'.replace(/(?=(?!^)(?:\d{3})+$)/g, ',')
returns: -2,000
correct: -2,000

You can use this regex:
var num = '-2000';
var repl = num.replace(/(\d)(?=(?:\d{3})+$)/m, '$1,');
or
var repl = num.replace(/(?=(?:\B\d{3})+$)/m, ',');
RegEx Demo

I suggest you to replace ^ with \b
(?=(?!\b)(?:\d{3})+$)
DEMO
(?!^) asserts that we are not at the start only, but (?!\b) asserts that we are not between a word char and a non-word character (vice-versa).
Example:
alert('-200'.replace(/(?=(?!\b)(?:\d{3})+$)/g, ','))
alert('-2000'.replace(/(?=(?!\b)(?:\d{3})+$)/g, ','))

To handle signed numbers, I'd recommend using something else than a regex
function formatInteger(num) {
var str = ('' + num).split('.')[0];
var sign = (str.charAt(0) === '-') && '-' || '';
if (sign) {
str = str.substr(1);
}
return sign + str.split('').reduceRight(function (result, char) {
if (result.length % 4 === 0) {
char += ',';
}
return char + result;
}, '').slice(0, -1);
}
If you feed this function a float, it will be truncated.
formatInteger(123456.123); // "123,456"
formatInteger(-1594504924) // "-1,594,504,924"

An other way:
var nb = '-2000000';
nb = nb.split(/\B/).reduce(function(p, c, i, a) {
return p + ((a.length-i)%3 ? c : ',' + c);
});

Related

Truncated a string with a number of characters without truncating words

I want to truncate a string with a limit of characters and a condition for the last character that should be a space (this way I have no truncated words)
Example :
var sentence = "The string that I want to truncate!";
sentence.methodToTruncate(14); // 14 is the limit of max characters
console.log("Truncated result : " + sentence); // Truncated result : The string
You can use truncate one-liner below:
const sentence = "The string that I want to truncate!";
const truncate = (str, len) => str.substring(0, (str + ' ').lastIndexOf(' ', len));
console.log(truncate(sentence, 14));
Here's how you can truncate by words and given limit -
String.prototype.methodToTruncate = function(n) {
var parts = this.split(" ");
var result = "";
var i = 0;
while(result.length >= n || i < parts.length) {
if (result.length + parts[i].length > n) {
break;
}
result += " " + parts[i];
i++;
}
return result;
}
var sentence = "The string that I want to truncate!";
console.log("Truncated result : " + sentence.methodToTruncate(14)); // Truncated result : The string
First you can have a max substring of your string, and then recursively remove the letters until you find spaces.
Note that this response is made without doing monkey patching and so, not extending String.prototype :
var sentence = "Hello a";
var a = methodToTruncate(sentence, 5); // 14 is the limit of max characters
console.log("Truncated result : " + a); // Truncated result : The string
function methodToTruncate(str, num) {
if(num>= str.length){ return str;}
var res = str.substring(0, num);
while (str[res.length] != " " && res.length != 0) {
console.log(res.length)
res = res.substring(0, res.length-1);
}
return res;
}

Convert sentence or camelCase word to spinal-case

I am trying to convert both sentence case and camel case to spinal case.
I am able to change camel case to by adding a space before every capital letter, but when I apply it to sentences with capital letters after spaces, I get extra spacing.
Here is my function so far :
function spinalCase(str) {
var noCamel = str.replace(/([A-Z])/g, ' $1');
var newStr = noCamel.replace(/\s|_/g, "-");
return newStr.toLowerCase();
}
spinalCase("makeThisSpinal"); //returns make-this-spinal
spinalCase("Make This Spinal"); //returns -make--this--spinal
Get lodash, specifically, https://lodash.com/docs#kebabCase.
_.kebabCase('makeThisSpinal') // make-this-spinal
_.kebabCase('Even Sentences Work') // even-sentences-work
Instead of:
var noCamel = str.replace(/([A-Z])/g, ' $1');
Try:
var noCamel = str.replace(/(\B[A-Z])/g, ' $1');
It's because you're replacing all capital letters with a space and its lowercase letter. So in your sentence, you're getting two spaces before this and spinal.
What you can do is replace all uppercase letters with "-$1" and then just remove all spaces from the string.
function spinalCase(str) {
var noCamel = str.replace(/([a-z](?=[A-Z]))/g, '$1 ')
var newStr = noCamel.replace(/\s|_/g, "-");
return newStr.toLowerCase();
}
spinalCase("makeThisSpinal"); //returns make-this-spinal
spinalCase("Make This Spinal"); //returns -make-this-spinal
Instead of str.replace(/([A-Z])/g, ' $1') for the camel case split, you should use str.replace(/([a-z](?=[A-Z]))/g, '$1 ') which will space out each word regardless of case.
Here's my solution, perhaps you will find it good reference:
function spinalCase(str) {
var newStr = str[0];
for (var j = 1; j < str.length; j++) {
// if not a letter make a dash
if (str[j].search(/\W/) !== -1 || str[j] === "_") {
newStr += "-";
}
// if a Capital letter is found
else if (str[j] === str[j].toUpperCase()) {
// and preceded by a letter or '_'
if (str[j-1].search(/\w/) !== -1 && str[j-1] !== "_") {
// insert '-' and carry on
newStr += "-";
newStr += str[j];
}
else {
newStr += str[j];
}
}
else {
newStr += str[j];
}
}
newStr = newStr.toLowerCase();
return newStr;
}

Convert string of time to cleaner format

There's usually some magical way to do something in javascript.
Take for example the string
10h49m02s
and wanting to convert it to
10 hours, 49 minutes, 2 seconds
while avoid empty hours/minutes/seconds
eg2
00h10m20s
This is what I'm doing which is probably hilarious
var arr = time.split('');
var hourMaj = arr[0];
var hourMin = arr[1];
var minMaj = arr[3];
var minMin = arr[4];
var secMaj = arr[6];
var secMin = arr[7];
var str = "";
if(hourMaj !== '0'){
str += hourMaj;
str += hourMin;
}else if (hourMin !== '0'){
str += hourMin;
}
if(hourMaj !== '0' || hourMin !== '0')
str += "hours, ";
... and on
You can actually use a regex to match your values and replace h, m and s with expanded words only if the captured texts are not zeros, like this:
var re = /\b0*(\d{1,2})h0*(\d{1,2})m0*(\d{1,2})s\b/g;
var str = '10h49m02s';
var str2 = '00h10m20s';
function func(match, h, m, s) {
var p = '';
if (h !== '0') {
p += h + " hours"
}
if (m !== '0') {
p += (p.length > 0 ? ", " : "") + m + " minutes"
}
if (s !== '0') {
p += (p.length > 0 ? ", " : "") + s + " seconds"
}
return p;
}
var res = str.replace(re, func);
document.write(res + "<br/>");
res = str2.replace(re, func);
document.write(res);
The regex - \b0*(\d{1,2})h0*(\d{1,2})m0*(\d{1,2})s\b - matches:
\b - word boundary
0* - 0 or more leading zeros
(\d{1,2}) - hours, 1 or 2 digits
h0* - h literally and 0 or more zeros
(\d{1,2}) - minutes, 1 or 2 digits
m0* - m literally and 0 or more zeros
(\d{1,2}) - seconds, 1 or 2 digits
s\b - s at the end of the "word".
Similar to stribizhev's answer, but with a much simpler regular expression. I've used reduce but a for loop is no more code and would probably be faster:
function parseTime(s) {
// Match sequences of numbers or letters
var b = s.match(/\d+|[a-z]+/gi);
var words = {h:'hour', m:'minute', s:'second'};
var result;
// If some matches found
if (b) {
// Do replacement
result = b.reduce(function(acc, p, i) {
// Only include values that aren't zero
// and skip letters - +p => NaN
if (+p) {
// Change letters to words, add plural and store in array
acc.push(+p + words[b[i+1]] + (p==1? '' : 's'));
}
// Pass the accumulator array to the next iteration
return acc;
},[])
}
// Format the result
return result.join(', ');
}
document.write(parseTime('00h00m02s') + '<br>');
document.write(parseTime('10h40m02s') + '<br>');
document.write(parseTime('10h00m51s') + '<br>');
document.write(parseTime('01h32m01s'));

Regex to allow numbers, plus symbol, minus symbol and brackets

I am trying to create a regex that allows only the following 0-9, plus symbol, minus symbol and brackets (). No limitations on length of each of the mentioned. So far I have this but it does not seem to work.
/^[0-9 -+]+$/
Hyphen - has to be at the end of charlist, else it means interval.
/^[0-9 ()+-]+$/
0-9 is possible to write shortly as \d
/^[\d ()+-]+$/
This should work for you:
^[\d\(\)\-+]+$
^ -> start of string
\d -> same as [0-9]
+ -> one or more repetitions
$ -> end of string
DEMO
var re = /^[\d\(\)\-+]+$/m;
var str = ['09+()1213+-','fa(-ds'];
var m;
var result = "";
for(var i = 0; i < str.length; i++) {
if ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
result += "\""+str[i]+ "\"" + " is matched:" + (m != null) + "</br>";
}
document.getElementById("results").innerHTML = result
<div id="results"></div>
To match digits, +, -, (, and ) use:
[+()\d-]+
The trick is the position of the characters inside the character class.
if (/^[+()\d-]+$/.test(text)) {
} else {
}
var re = /^[\w\(\)\-\!\+\*\&\%\$#\#\[\]\{\}\<\>\s]+$/m;
var str = ['09+()1213+-[#test#gmail{}<>','fa(-ds'];
var m;
var result = "";
for(var i = 0; i < str.length; i++) {
if ((m = re.exec(str[i])) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
result += "\""+str[i]+ "\"" + " is matched:" + (m != null) + "</br>";
}
document.getElementById("results").innerHTML = result
<div id="results"></div>
[\d\(\)\+\-\(\)]
That should do it.
EDIT: But since some agree the escaping is too much, here ya go:
[\d+()-]

Format number string using commas

I want to format numbers. I have seen some of the regex expression example to insert comma in number string. All of them check 3 digits in a row and then insert comma in number. But i want something like this:
122 as 122
1234 as 1,234
12345 as 12,345
1723456 as 17,23,456
7123456789.56742 as 7,12,34,56,789.56742
I am very new to regex expression. Please help me how to display the number as the above. I have tried the below method. This always checks for 3 digits and then add comma.
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
But i want comma every 2 digits except for the last 3 digits before the decimals as shown above.
The result will depend on your browsers locale. But this might be an acceptable solution:
(7123456789.56742).toLocaleString();
Outputs:
7,123,456,789.56742
Try it and see if it outputs 7,12,34,56,789.567421 in your locale.
Here's a function to convert a number to a european (1.000,00 - default) or USA (1,000.00) style:
function sep1000(somenum,usa){
var dec = String(somenum).split(/[.,]/)
,sep = usa ? ',' : '.'
,decsep = usa ? '.' : ',';
return dec[0]
.split('')
.reverse()
.reduce(function(prev,now,i){
return i%3 === 0 ? prev+sep+now : prev+now;}
)
.split('')
.reverse()
.join('') +
(dec[1] ? decsep+dec[1] :'')
;
}
Alternative:
function sep1000(somenum,usa){
var dec = String(somenum).split(/[.,]/)
,sep = usa ? ',' : '.'
,decsep = usa ? '.' : ',';
return xsep(dec[0],sep) + (dec[1] ? decsep+dec[1] :'');
function xsep(num,sep) {
var n = String(num).split('')
,i = -3;
while (n.length + i > 0) {
n.splice(i, 0, sep);
i -= 4;
}
return n.join('');
}
}
//usage for both functions
alert(sep1000(10002343123.034)); //=> 10.002.343.123,034
alert(sep1000(10002343123.034,true)); //=> 10,002,343,123.034
[edit based on comment] If you want to separate by 100, simply change i -= 4; to i -= 3;
function sep100(somenum,usa){
var dec = String(somenum).split(/[.,]/)
,sep = usa ? ',' : '.'
,decsep = usa ? '.' : ',';
return xsep(dec[0],sep) + (dec[1] ? decsep+dec[1] :'');
function xsep(num,sep) {
var n = String(num).split('')
,i = -3;
while (n.length + i > 0) {
n.splice(i, 0, sep);
i -= 3; //<== here
}
return n.join('');
}
}
use toLocaleString();
It automatically handles inserting commas and will also handle uk strings the right way
e.g.
var num=63613612837131;
alert(num.toLocaleString());
Below is the snippet of code, can be done in better way but this works :D
function formatDollar(num)
{
var p = num.toFixed(2).split(".");
var chars = p[0].split("").reverse();
var sep1000 = false;
var newstr = '';
var count = 0;
var count2=0;
for (x in chars)
{
count++;
if(count%3 == 1 && count != 1 %% !sep1000)
{
newstr = chars[x] + ',' + newstr;
sep1000=true;
}
else
{
if(!sep1000)
{
newstr = chars[x] + ',' + newstr;
}
else
{
count2++;
if(count%2 == 0 && count != 1)
{
newstr = chars[x] + ',' + newstr;
}
else
{
newstr = chars[x] + newstr;
}
}
}
}
return newstr + "." + p[1];
}

Categories

Resources