This question already has answers here:
How to format a number with commas as thousands separators?
(50 answers)
Closed 6 years ago.
I'm getting large numbers as input and want to display them with a small space for every step of thousand (every 3 digits). So I'm looking for an array of max. three digits as output.
Examples:
Input: 10 Output: [10]
Input: 1234 Output: [1, 234]
Input: 24521280 Output: [23, 521, 280]
It does not matter if the output array contains strings or numbers.
What would be a most elegant (comprehensive / short) solution in Javascript ES6?
I wrote two working solutions, but I feel that they are overly complicated or that I'm missing something:
Solution 1)
function numberToThreeDigitArray(number) {
if (number / 1000 < 1) return [number];
return [
...numberToThreeDigitArray(Math.floor(number / 1000)),
number % 1000
];
}
Solution 2)
function numberToThreeDigitArray(number) {
return number.toString().split('').reverse().map((char, i) => {
return i !== 0 && i % 3 === 0
? ' ' + char
: char;
}).join('').split('').reverse().join('').split(' ');
}
number.toLocaleString().split(',').map(num => +num) should do it for you.
See the toLocaleString MDN docs.
Example:
const arr = (24521280).toLocaleString().split(',').map(num => +num)
// [24, 521, 280]
// or
function getNumber(n) {
return n.toLocaleString().split(',').map(num => +num)
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 months ago.
Improve this question
I have a task to create a JS script that is able to find a string using binary search on an array containing all permutations of the alphabetic chars (only lower case) with length 6 - meaning all strings of this form:
['aaaaaa','aaaaab','aaaaac'.... 'zzzzzx','zzzzzy','zzzzzz']
(For a total of 26^6 items in the array)
Due to its size - I cannot generate the array locally and run a regular binary search on it, I need to be able to find the string in the n/2 position (n = 26^6) without creating the array.
On the other hand - I need to create some sort of 1-to-1 mapping between any string ('aaaaaa', 'zzzzzz') to a number and the other way around (from number to a string) which I can then make division calculations on and find the middle string and so on.
Preferably this should be in JS/TS as I want to make a node app out of it in the end.
Any ideas?
You can do something that works like binary numbers, I mean write the number in base26 and just use the exponant to find the corresponding letter at the corresponding spot.
let number = (26**6)/2
let exponants = number.toString(26)
let correspondingString = exponants
.split('')
.map(elem => parseInt(elem, 26))
.map(elem => (elem + 10).toString(36))
.join('')
console.log(correspondingString);
And reverse :
let string = 'naaaaa'
let correspondingNumber = string
.split('')
.map(elem => parseInt(elem, 36) - 10)
.map((elem, index) => elem*(26**(5-index)))
.reduce((sum, value)=> sum + value, 0)
console.log(correspondingNumber);
Note
This solution somewhat generalizes the question to larger numbers. The numbers relevant to the question can still be accomodated by the standard JS number type.
Solution
You can find the a-z representation for a given number by using JS's BigInt object (arbitrary size integers).
In case you are looking for the n/2-th number in a sorter permutation list, you'd go as follows:
let bn_x = ((26n ** 6n) / 2n) // BigInt notation
, s_x26 = bn_x.toString(26) // Convert in base 26. Digits are represented by 0-9,a-q
, s_atoz // Will hold s_x26 with digits represented by a-z
;
s_atoz =
Array
.from(s_x26) // string -> array of chars (ie. array of single-letter strings)
.map ( c => { // map a-q -> k-z, 0-9 -> a-j
return String.fromCharCode((( c.charCodeAt(0) < 'a'.charCodeAt(0) ) ? (c.charCodeAt(0) + ( 'a'.charCodeAt(0) - '0'.charCodeAt(0) )) : ( c.charCodeAt(0) + 10 )));
})
.join('') // array of chars -> string
;
console.log(s_atoz);
Of course, this specific result can also be deduced without computation.
The other way round works similar wrt the basic idea, but with a caveat: There is no radix-aware BigInt constructor at the time of writing, so the number needs to be assembled using the elementary steps from radix construction.
let s_atoz = 'naaaaa'
, abn_x26 =
Array
.from(s_atoz)
.map ( c => {
return BigInt(c.charCodeAt(0) - 'a'.charCodeAt(0));
})
, bn_x = abn_x26.reduce ( (previousValue, currentValue) => {
return BigInt(previousValue) * 26n + BigInt(currentValue);
}
, 0n
)
;
console.log(bn_x.toString());
If you just want to find the string that would occur at the given position in our imaginary array, we can calculate it with this numberToString function:
const n2s = (chars, len = chars .length) => (n) =>
(n < len ? '' : n2s (chars, len) (~~ (n / len)))
+ chars [n % len]
const fixedN2s = (digits, chars) => (n) =>
n2s (chars) (n) .padStart (digits, chars [0])
const numberToString = fixedN2s (6, 'abcdefghijklmnopqrstuvwxyz')
; [28, 268041553, 202214284, 26 ** 6 / 2] .forEach (
s => console .log (`numberToString (${s}) //=> "${numberToString (s)}"`)
)
We start with a helper function that does the bulk of the work, accepting first the alphabet we want to use. Here it's all the lower-case letters, but we could easily imagine doing the same against "abcde", for instance. It returns a function which takes a number, and then we peel off the last "digit: of that number, using it as an index into chars for the last character, and then for the rest of the string either returning an empty string (in our base case when n is less than our character count) or the value of a recursive call with that digit stripped and the remaining number shifted over by dividing our character count into the remainder.
We layer on a function, fixedN2s, which calls the above with an additional digits argument that tells the number of fixed positions to prefill with the first character. That is, n2s ('abc...z') (28) would yield 'bc', but we want to prefill with a, to get 'aaaabc'.
We use pass 6 and our alphabet to to this function to create numberToString, our main function.
Note that we could do the reverse simply enough as well, with somthing like this snippet:
const s2n = (chars,
encoding = [...chars] .reduce ((a, d, i) => ((a [d] = i), a), {})
) => ([...ss]) => ss .length == 0
? 0
: chars .length * s2n (chars, encoding) (ss .slice (0, -1)) + encoding [ss .at (-1)]
const stringToNumber = s2n ('abcdefghijklmnopqrstuvwxyz')
; ['abc', 'woolen', 'random', 'naaaaa'] .forEach (
s => console .log (`stringToNumber ("${s}") //=> ${stringToNumber (s)}`)
)
This question already has answers here:
What's the fastest way to convert String to Number in JavaScript?
(10 answers)
Closed 3 years ago.
Convert string to any number
Way 1
console.log(+"3")
Way 2
console.log("3" * 1)
Way 3
console.log(~~ "3")
Way 4
console.log(parseInt("3"))
console.log(parseFloat("3"))
All the above results are providing same results. But individually it may give some additional functionalities. But I want to know which one is best for performance?
I think "1"*1 (way-2) is one of the best way to convert string to int. Is it correct? If I am wrong, then please let me know which one is best and why?
But I want to know which one is best for performance?
Test it yourself
const n = 3
function first (num) {
return +num
}
function second (num) {
return num * 1
}
function third (num) {
return ~~ num
}
function forth (num) {
return parseInt(num)
}
const count = 10000000
const data = new Array(count).fill(n);
console.time('first')
data.map(first)
console.timeEnd('first')
console.time('second')
data.map(second)
console.timeEnd('second')
console.time('third')
data.map(third)
console.timeEnd('third')
console.time('forth')
data.map(forth)
console.timeEnd('forth')
With random number
function first (num) {
return +num
}
function second (num) {
return num * 1
}
function third (num) {
return ~~ num
}
function forth (num) {
return parseInt(num)
}
const data = "34 123456789 0 0.1 10 15s 1,000 011 45 4512 459 8348 3418 2342.3 4.5 34134343 341234034 3434 340 3481 3869 38906 4 1 2 45 48 38.3 xx 341,430,341 34 123456789 0 0.1 10 15s 1,000 011 45 4512 459 8348 3 906".split(' ');
console.time('first')
data.map(first)
console.timeEnd('first')
console.time('second')
data.map(second)
console.timeEnd('second')
console.time('third')
data.map(third)
console.timeEnd('third')
console.time('forth')
data.map(forth)
console.timeEnd('forth')
This question already has answers here:
Pad a number with leading zeros in JavaScript [duplicate]
(9 answers)
Closed 4 years ago.
guys.
I'm having some issues with this function
const incrementString = str => {
if (!str.match(/[\d+]$/)){
return str += 1
} else{
return str.replace(/[\d+]$/, ch => new Number(ch) + 1)
}
}
What I'm trying to do with that function is + 1 the number at the end of the string, and if the string doesn't has one, I'll add a 1 at the end.
string expected
"foobar000" "foobar001"
"foo" "foo1"
"foobar025" "foobar026"
I don't know if it's possible to do it with replace and regex, I have in mind a solution with loops, .length, split, etc..., but I want to do it with regex, if it's possible.
Problem: How can I take the number at the end of the string, with the leading zeros, and sum them a 1?
this are some examples of the bad behavior of my function
Expected: 'foobar011', instead got: 'foobar11'
Test Passed: Value == 'foo1'
Expected: 'foobar002', instead got: 'foobar2'
Test Passed: Value == 'foobar100'
Test Passed: Value == 'foobar100'
Test Passed: Value == '1'
Thanks and happy holydays
You could store the length of the numerical string and apply after incrementing the wanted leading zeroes.
function increment(s) {
var [left, right = '0'] = s.split(/(\d*$)/),
length = right.length;
return left + (+right + 1).toString().padStart(length, '0');
}
console.log(['foobar000', 'foo', 'foobar025'].map(increment));
I used all your hints and answers to check different options to solve my problem.
Finally, I solved with the "String of numbers" and the padStart hints.
const incrementString = str => {
if (str.match(/[0-9+]+/g)) {
let numbers = str.replace(/[a-z+]+/g, "")
return str.replace(numbers, (Number(numbers) + 1 + '').padStart(numbers.length, 0))
} else {
return str + 1
}
}
I hope this helps others as it helped to me.
Thanks and happy holydays
This question already has answers here:
How can I pad a value with leading zeros?
(76 answers)
Closed 9 years ago.
I can't figure out how to solve the following problem.
I have an array of numbers from 1 to 100.
I need to convert them to strings but to a length of 5.
So, for instance:
1 becomes 00001
2 becomes 00002
3 becomes 00003
4 becomes 00004
etc, etc..
It seems so easy but I cannot find a function. The best I found was .toFixed(n) which is the number of decimal points to use.
Here's a very simple padding function:
function padLeft(str, length, paddingCharacter) {
str = '' + str; //Make sure that we convert it to a string if it isn't
while (str.length < length) {
str = paddingCharacter + str; //Pad it
}
return str;
}
padLeft(123, 5, '0'); //00123
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert a number to the shortest possible character string while retaining uniqueness
I want to count something and I only have a single digit to report the result, so I want to use letters for numbers > 9. E.g.
1 => 1
5 => 5
10 => A
30 => U
55 => u // I may have an off-by-one error here -- you get the idea
>61 => z // 60 will be more than enough, so I'll use z to mean "at least 62"
What's the easiest way to do that using javascript?
Here's one of the many ways to do it:
function num2letter(num) {
if( num > 61) return "z";
if( num < 0) return num;
return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[num];
}
I decided base 36 was good enough:
function oneDigit(n) {
var BASE=36;
if (n >= BASE-1) { n = BASE-1; }
return n.toString(BASE);
}
Another way to do it:
function parse(x)
{
if(x<10)return x;
else if(x<36)return String.fromCharCode(x+55).toUpperCase();
else if(x<62)return String.fromCharCode(x+29).toLowerCase();
else return "z";
}
And this little test:
var res="";
for(var a=-10;a<70;a++)res+=a+" -> "+parse(a)+"\n";
alert(res);
And a fiddle: http://jsfiddle.net/nD59z/4/
And the same way, but with less characters and incomprehensible:
function parse(x)
{
return x<10?x:(x<36?String.fromCharCode(x+55).toUpperCase():(x<62?String.fromCharCode(x+29).toLowerCase():"z"));
}