Add a colon after two characters without using String.replace - javascript

I am currently using replace to insert a colon after the second character of a four-character string (1000). I think it is an elegant solution. But I wonder if there are any other elegant solutions for this? Thanks for your ideas!
Working code
const myStr = "1000";
const string = myStr.replace(/(\d{2})(\d{2})/g, '$1:$2');
console.log(string);

You could stil take a regular expression which works for any time length, like four or six digits with colon for each group of two.
const
format = s => s.replace(/.(?=(..)+$)/g, '$&:');
console.log(format('1000'));
console.log(format('100000'));

Keep it simple. Use string functions to manipulate strings:
const s1 = "1000";
const s2 = s1.slice(0, 2) + ":" + s1.slice(2);
console.log(s2);

Definitely not the best way to do that, i'm just wondering how many alternatives there are
[...'1000'].map((c, i) => i !== 0 && i % 2 === 0 ? `:${c}` : c).join('') //10:00
[...'100000'].map((c, i) => i !== 0 && i % 2 === 0 ? `:${c}` : c).join('') //10:00:00
[...'10000000'].map((c, i) => i !== 0 && i % 2 === 0 ? `:${c}` : c).join('') //10:00:00:00

You can use template literals:
const x = "1000"
const result = `${x.slice(0, 2)}:${x.slice(2)}`
console.log(result)

You can try a substring, somthing like this
var mystring = '1000';
var method1 = mystring.substring(0, 2) + ':' + mystring.substr(2);
console.log(method1);
and u can make your own function
String.prototype.insert = function(index, string) {
if (index > 0){
return this.substring(0, index) + string + this.substr(index);
}
return string + this;
};
var mystring='1000';
var method2=mystring.insert(2,':');
console.log(method2);

Related

How to best sort an array of strings with comma delimited numbers _and_ symbols in JavaScript

What's the best approach to sort() an array of strings containing comma delimited numbers and symbols in JavaScript?
My array looks like this:
var uniqueValues = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"]
and I need it to look like this:
[">1,000,000", ">750,000", ">500,000", ">250,000", ">100,000", "<100,000"]
Below you can see what I've tried thus far. #1 to get around the alphanumeric issue (using a combo of sort & localeCompare) and #2 to attempt to weigh ">" higher than "<" for example (thanks to this SO answer, but I can't figure out how to both weigh the symbol, as well as correctly sort the comma-delimited numbers. Here are the approaches I've tried without success:
1. uniqueValues.sort((a,b) => a.localeCompare(b));
2. var sortOrder = {
'>': 1,
'<': 2
}
uniqueValues.sort(function (a, b) {
var oa = sortOrder[a[0]] || 2;
var ob = sortOrder[b[0]] || 2;
if (oa > ob)
return 1;
else if (oa < ob)
return -1;
else
return 0;
});
A slightly different approach is to use a parse method since you don't exactly want to sort according to string values. You rather want to sort according to the order of magnitude they represent.
Let assume that each expression should be interpreted as a bigger number ('>') or smaller number ('<'). That can be translated to +1 / -1. Then, replace all dots and commas in the remaining part for it to be an integer and sum both parts.
The solution can be as simple as a sort according to that parse method.
var uniqueValues = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"];
function parseExpr(exp) {
return (exp[0] == '<' ? -1 : 1) + parseInt(exp.replace(/[,.]/g, '').substr(1));
}
uniqueValues.sort((a,b) => parseExpr(b) - parseExpr(a));
console.log(uniqueValues);
Add 1 to the number if it includes >, then sort:
var uniqueValues = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"]
var s2i = (s) => {
let n = parseInt(s.replace(/[^\d]/g, ''))
return n + (s.includes('>') ? 1 : 0)
};
uniqueValues.sort((a,b) => Math.sign(s2i(a) - s2i(b)));
console.log(uniqueValues)
Not the most elegant or robust solution, but very simple:
uniqueValues.sort((a, b) => {
const aStr = a.substring(1)
const bStr = b.substring(1)
if (aStr == bStr) {
return a < b ? 1 : -1
}
const aInt = parseInt(bStr.split(',').join(''))
const bInt = parseInt(aStr.split(',').join(''))
return aInt - bInt
})
Convert your Strings into Numbers, and use an epsilon estimation instead of < and > for comparing.
Here's the code:
var a = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"];
var epsilon = 0.000001; // Choose whatever precision you require.
function toNumber(x) {
var signedEpsilon = (x[0] === "<" ? -epsilon : epsilon); // signed epsilon.
return parseFloat(x.slice(1).replace(/,/g, "")) + signedEpsilon;
}
a.sort((x, y) => toNumber(x) < toNumber(y));
Create a map of strings to numeric values using Array#reduce then sort using the numeric values from the map:
var uniqueValues = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"];
var valuesMap = uniqueValues.reduce(function(map, v) {
// convert to number by removing all non numeric characters, parsing, and convert the sign to a number
map[v] = {
value: +v.replace(/[^\d]/g, ''),
sign: v[0] === '>' ? 1 : -1
};
return map;
}, Object.create(null));
// sort using the corresponding values from the map - if the values are equal compare the signs
uniqueValues.sort(function(a, b) {
var am = valuesMap[a];
var bm = valuesMap[b];
return bm.value - am.value || bm.sign - am.sign;
});
console.log(uniqueValues);
And the ES6 version using a Map instead of a plain object:
var uniqueValues = ["<100,000", ">100,000", ">250,000", ">500,000", ">1,000,000", ">750,000"];
// convert to number by removing all non numeric characters, parsing, and convert the sign to a number
const valuesMap = uniqueValues.reduce((map, v) =>
map.set(v, {
value: +v.replace(/[^\d]/g, ''),
sign: v[0] === '>' ? 1 : -1
}), new Map());
// sort using the corresponding values from the map - if the values are equal compare the signs
uniqueValues.sort((a, b) => {
const am = valuesMap.get(a);
const bm = valuesMap.get(b);
return bm.value - am.value || bm.sign - am.sign
})
console.log(uniqueValues);

Can anybody refactor this function that takes a number as an argument and reverses its digits?

Given a number, write a function to output its reverse digits. (e.g. given 123 the answer is 321)
Numbers should preserve their sign; i.e. a negative number should still be negative when reversed.
This was my solution:
function reverseNumber(n) {
var split = (""+n).split("");
var reverse = split.reverse();
var last = reverse.join('');
if(reverse[reverse.length - 1] == '-') {
var almost = reverse.pop();
var close = reverse.unshift(almost);
var last2 = reverse.join('');
var rev = Number(last2);
return rev;
} else {
var pos = Number(last);
return pos;
}
}
It's too long. I'm wondering if anybody can come up with a shorter solution.
You can use .reduceRight(), .join(), + operator
+((...props) => props.reduceRight((a, b) => a.concat(b), []))(1,2,3).join("")
var numRev2 = function(n) {
return n >= 0
? n.toString().split('').reverse().join('')
: '-' + n.toString().substring(1).split('').reverse().join('');
}
//ES6
var numRev = n =>
n > 0 ? n.toString().split('').reverse().join('')
: '-' + n.toString().substring(1).split('').reverse().join('');
console.log ( numRev(743823) );
console.log ( numRev(-743823) );
console.log ( numRev2(743823) );
console.log ( numRev2(-743823) );
Some useful information is available at How do you reverse a string in place in JavaScript?
Since this has devolved to code golf, another answer won't hurt.
function revNum(n) {
return (n<0? -1 : 1) * ('' + Math.abs(n)).split('').reverse().join('');
}
[-12.3, 345.23, -0.765, 1.23e5].forEach(n=>console.log(n + ' : ' + revNum(n)));

Javascript replace every 6th colon in array

I have some problems with replacing every 6th colon in my array. Have tried something with Regex, but that doesn't seem to work. I have red other questions were people are using nth and then set this variabele to the index you want to replace, but can't figure out why that isn't working. I used the join function to replace the ',' in my array with ':'.
arrayProducts[i] = arrayProducts[i].join(':');
When i use console.log(arrayProducts); this is my result:
F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3
This is what I want:
F200:0:0.0000:1:100:0:1,KPO2:0:0.0000:1:200:0:2,HGB1:0:0.0000:1:300:0:3
Thanks for reading!
Edit: F200, KP02 and HGB1, could also be numbers / digits like: 210, 89, 102 so the :[A-Z] method from regex doesn't work.
You can just count the number of colon occurences and replace every nth of them.
var str = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3', counter = 0;
res = str.replace(/:/g, function(v) {
counter++;
return !(counter % 7) ? ',' : v;
});
console.log(res);
A regex solution is viable. You can use a function as the second parameter of the .replace method to make full use of backreferences.
var str = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3';
str = str.replace(/((?:[^:]*:){6}(?:[^:]*)):/g, function() {
var matches = arguments;
return matches[1] + ',';
});
console.log(str);
What you are looking for is to split over the following expression :[A-Z]
(assuming that your rows always start with this range)
a simple solution could be:
mystring.split(/:[A-Z]/).join(',')
/:[A-Z]/ matches any : followed by a uppercase letter
You could use replace with a look for six parts with colon and replace the seventh.
var string = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3',
result = string.replace(/(([^:]*:){6}[^:]*):/g, '$1,');
console.log(result);
Another solution (based on the number of iteration)
using map method:
str.split(':').map((v, i) => (i % 7 === 0 ? ',' : ':') + v ).join('').slice(1)
using reduce method:
str.split(':').reduce((acc,v, i) => {
return acc + (i % 7 === 0 ? ',' : ':' ) + v ;
}, '').slice(1)
Note: arrow expression does not work on old browsers
maybe you can try this approach,
loop your array and join it manually, something like :
var strarr = "F200:0:00000:1:100:0:1:KPO2:0:00000:1:200:0:2:HGB1:0:00000:1:300:0:3";
var arr = strarr.split(":")
var resStr = "";
for(var i = 0; i < arr.length; i++)
{
if(i > 0 && i%7 == 0)
resStr = resStr + "," + arr[i]
else
resStr = resStr + ( resStr == "" ? "" : ":") + arr[i];
}
console.log(resStr);

Re-write malformed dates yyyy-M-d to yyyy-MM-dd in javascript using RegEx

So I'm rewriting dates in javacript and as familiar js spits dates like 2013-1-1 that isn't very useful always. Instead I'm looking for a routine that will form this date to the correct iso-version 2013-01-01
Today I make this by using string
var b = new Date('2013-1-1');
var result = b.getFullYear() + "-" +
(b.getMonth().toString().length == 1 ? "0" + parseInt(b.getMonth() + 1) : parseInt(b.getMonth() + 1)) + "-" +
(b.getDate().toString().length == 1 ? "0" + b.getDate() : b.getDate());
This works but it is ugly. Is there a better way to perform this using RegEx?
Please spare me of any anti-regex comments
A non-regex solution would be a generic padding function. First get your date in the non-padded version then you can split on the separator and pad it as necessary. Something like this:
var date = '2013-1-1';
var pad = function(n) {
return function(str) {
while (str.length < n) {
str = '0'+ str;
}
return str;
}
};
date = date.split(/-/g).map(pad(2)).join('-'); //=> 2013-01-01
may be this could help:
var str="2013-1-1";
var m = str.match(/^(\d{4})-(\d{1})-(\d{1})$/);
console.log([m[1], "0".concat([2]-1), "0".concat(m[3])].join('-'));
based on elclanrs suggestion I wrote an extension method
// Add 0 to single numbers
Number.prototype.padDate = function () {
// Add +1 if input is 0 (js months starts at 0)
var number = this == 0 ? 1 : this;
return number.toString().length == 1 ? "0" + number : number;
};
This allows me to build dates like this
var b = new Date('2013-1-1');
var result = b.getFullYear() + "-" + b.getMonth().padDate() + "-" + b.getDate().padDate();
Much cleaner, thanks

add commas to a number in jQuery

I have these numbers
10999 and 8094 and 456
And all i want to do is add a comma in the right place if it needs it so it looks like this
10,999 and 8,094 and 456
These are all within a p tag like this <p class="points">10999</p> etc.
Can it be done?
I've attempted it here with the help of other posts http://jsfiddle.net/pdWTU/1/ but can't seem to get it to work
Thanks
Jamie
UPDATE
Messed around a bit and managed to figure it out here http://jsfiddle.net/W5jwY/1/
Going to look at the new Globalization plugin for a better way of doing it
Thanks
Jamie
Works on all browsers, this is all you need.
function commaSeparateNumber(val){
while (/(\d+)(\d{3})/.test(val.toString())){
val = val.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
return val;
}
Wrote this to be compact, and to the point, thanks to regex. This is straight JS, but you can use it in your jQuery like so:
$('#elementID').html(commaSeparateNumber(1234567890));
or
$('#inputID').val(commaSeparateNumber(1234567890));
However, if you require something cleaner, with flexibility. The below code will fix decimals correctly, remove leading zeros, and can be used limitlessly. Thanks to #baacke in the comments.
function commaSeparateNumber(val){
val = val.toString().replace(/,/g, ''); //remove existing commas first
var valRZ = val.replace(/^0+/, ''); //remove leading zeros, optional
var valSplit = valRZ.split('.'); //then separate decimals
while (/(\d+)(\d{3})/.test(valSplit[0].toString())){
valSplit[0] = valSplit[0].toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
if(valSplit.length == 2){ //if there were decimals
val = valSplit[0] + "." + valSplit[1]; //add decimals back
}else{
val = valSplit[0]; }
return val;
}
And in your jQuery, use like so:
$('.your-element').each(function(){
$(this).html(commaSeparateNumber($(this).html()));
});
Here's the jsFiddle.
Number(10000).toLocaleString('en'); // "10,000"
Timothy Pirez answer was very correct but if you need to replace the numbers with commas Immediately as user types in textfield, u might want to use the Keyup function.
$('#textfield').live('keyup', function (event) {
var value=$('#textfield').val();
if(event.which >= 37 && event.which <= 40){
event.preventDefault();
}
var newvalue=value.replace(/,/g, '');
var valuewithcomma=Number(newvalue).toLocaleString('en');
$('#textfield').val(valuewithcomma);
});
<form><input type="text" id="textfield" ></form>
Take a look at recently released Globalization plugin to jQuery by Microsoft
Take a look at Numeral.js. It can format numbers, currency, percentages and has support for localization.
function delimitNumbers(str) {
return (str + "").replace(/\b(\d+)((\.\d+)*)\b/g, function(a, b, c) {
return (b.charAt(0) > 0 && !(c || ".").lastIndexOf(".") ? b.replace(/(\d)(?=(\d{3})+$)/g, "$1,") : b) + c;
});
}
alert(delimitNumbers(1234567890));
I'm guessing that you're doing some sort of localization, so have a look at this script.
Using toLocaleString
ref at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
function formatComma(value, sep = 0) {
return Number(value).toLocaleString("ja-JP", { style: "currency", currency: "JPY", minimumFractionDigits: sep });
}
console.log(formatComma(123456789, 2)); // ¥123,456,789.00
console.log(formatComma(123456789, 0)); // ¥123,456,789
console.log(formatComma(1234, 0)); // ¥1,234
another approach:
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
var a = addCommas(10000.00);
alert(a);
Another amazing plugin:
http://www.teamdf.com/web/jquery-number-format/178/
Another way to do it:
function addCommas(n){
var s = "",
r;
while (n) {
r = n % 1000;
s = r + s;
n = (n - r)/1000;
s = (n ? "," : "") + s;
}
return s;
}
alert(addCommas(12345678));
Here is my coffeescript version of #baacke's fiddle provided in a comment to #Timothy Perez
class Helpers
#intComma: (number) ->
# remove any existing commas
comma = /,/g
val = number.toString().replace comma, ''
# separate the decimals
valSplit = val.split '.'
integer = valSplit[0].toString()
expression = /(\d+)(\d{3})/
while expression.test(integer)
withComma = "$1,$2"
integer = integer.toString().replace expression, withComma
# recombine with decimals if any
val = integer
if valSplit.length == 2
val = "#{val}.#{valSplit[1]}"
return val

Categories