Count function and number - javascript

Write a function - countNumbers It should accept string with different symbols and return an object which contains counts of each number.
Tip: consider reusing makeNumber function.
My solution is not full, what should i do the next?
function countNumbers (string) {
let numbers = [];
for (let i = 0; i < string.length; i++) {
if (!isNaN(parseInt(string[i]))){
numbers.push([string[i]])
}
}
return numbers.join('');
};
for example: countNumbers('erer384jj4444666888jfd123');
// => {'1': 1, '2': 1, '3': 2, '4': 5, '6': 3, '8': 4}
countNumbers('jdjjka000466588kkkfs662555');
// => {'0': 3, '2': 1, '4': 1, '5': 4, '6': 4, '8': 2}

You can use an object instead of an array, and check if the property already exists. If it does then add 1, else set it to start with 1.
In your code you return a string with return numbers.join(''); but in this case your can return the object instead.
function countNumbers(string) {
let numbers = {};
for (let i = 0; i < string.length; i++) {
let val = string[i];
if (!isNaN(parseInt(val))) {
val in numbers ? numbers[val]++ : numbers[val] = 1;
}
}
return numbers;
}
console.log(countNumbers('erer384jj4444666888jfd123'));
console.log(countNumbers('jdjjka000466588kkkfs662555'));
Or as pointed out by #secan as an alternative solution you can use a pattern [0-9] with the global flag /g to get the digits from the string.
const countNumbers = str => {
const counterObj = {};
str.match(/[0-9]/g).forEach(
s => counterObj.hasOwnProperty(s) ? counterObj[s] += 1 : counterObj[s] = 1
);
return counterObj;
}
console.log(countNumbers('erer384jj4444666888jfd123'));
console.log(countNumbers('jdjjka000466588kkkfs662555'));

Related

Incrementing a value in an object

I'm working on finding the mode for a given array. The way I've gone about it so far is to reduce the array into object keys, and set each of the key values to zero. Now I want to scan the array again and increment the value by 1 for each occurrence of the element in the array.
I have what I think should work, but the key with multiple occurrences isn't getting incremented. All values just read as 1.
My code so far:
const mode = function(arr) {
const reducer = arr.reduce((accumulator, currentValue) => (accumulator[currentValue] = 0, accumulator), {});
for (let key in reducer) {
for (let i = 0; i < arr.length; i++) {
if (reducer[key] === arr[i]) {
reducer[key]++;
}
}
}
return reducer;
};
console.log(mode([6,2,3,4,9,6,1,0,5]));
Which returns:
{ '0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '9': 1 }
What am I missing to change '6': 1 to '6': 2 ?
Any guidance is appreciated. Still getting the hang of things, open to any suggestions or feedback. Thank you!
The error in your code (as noted by #Pointy) is the comparison reducer[key] === arr[i] that should be if (key === arr[i]) {. Since you are using strict equality (===) you'll need to cast the key to a number, or use the equality (==) operator instead.
const mode = function(arr) {
const reducer = arr.reduce((accumulator, currentValue) => (accumulator[currentValue] = 0, accumulator), {});
for (let key in reducer) {
for (let i = 0; i < arr.length; i++) {
if (+key === arr[i]) {
reducer[key]++;
}
}
}
return reducer;
};
console.log(mode([6, 2, 3, 4, 9, 6, 1, 0, 5]));
However, you are doing some redundant work, since you can compute the number of occurrences when you reduce the array to an object:
const mode = function(arr) {
return arr.reduce((accumulator, currentValue) => {
accumulator[currentValue] = (accumulator[currentValue] ?? 0) + 1;
return accumulator;
} , {});
};
console.log(mode([6,2,3,4,9,6,1,0,5]));

How to reorder an Array to avoid consecutive duplicates

I have an array of numbers [1,2,2,2,3,4,5]
What I want to do is to sort the array to avoid equal numbers consecutively [1,2,3,2,4,2,5]. but I don't want to delete any number from the array, in the worse case when the duplicated numbers are more than the other numbers I would like to put those that are impossible to merge in other arrays.
const original = [1,2,2,2,2,2,2,3,4];
const merged = [];
const rest = [];
For example [1,2,2,2,2,2,2,3,4] the result expected should be [2,1,2,3,2,4,2] and another array with [2,2] in the original array I have 6 times 2 and I was able to merge 4 of the six in the rest
const original = [1,2,2,2,2,2,2,3,4];
const merged = [2,1,2,3,2,4,2];
const rest = [2,2];
I was trying to play with this algorithm but there is no way to get the respected result, this algorithm deletes the duplicates
const testArr = [1, 1, 2, 2, 3, 3, 1, 1, 1];
const compress = (arr, len = 0, canDelete = false) => {
if(len < arr.length){
if(canDelete){
arr.splice(len, 1);
len--;
}
return compress(arr, len+1, arr[len] === arr[len+1])
};
return;
};
compress(testArr);
console.log(testArr);
Any Idea on what is the best way to face this kind of problem?
It was a very interesting one, here is my solution:
const original = [1,2,2,2,2,3,3,2,2,2,3,4]
console.log("Before: ", original)
let object_keys = {}
//Step 1: map all the values and how many times it duplicated
for(let val of original){
if(object_keys[val]){
object_keys[val]++
}else{
object_keys[val] = 1
}
}
console.log(object_keys) // { '1': 1, '2': 7, '3': 3, '4': 1 }
//Step 2: Run over the object and create a new array. the method is each iterate, append new key
const get_the_most_duplicated_val = (object_keys, except) => {
let max = 0
let key = ''
for(let v in object_keys){
if(object_keys[v] > max && !except.includes(v)){
max = object_keys[v]
key = v
}
}
return key
}
let merged = []
let rest = []
let merged_is_completed = false
while(!merged_is_completed){
const append_val = (key) => {
merged.push(key)
object_keys[key]--
if(object_keys[key] == 0){
delete object_keys[key]
}
}
const last_val = () => {
return merged[merged.length - 1]
}
let most_key = get_the_most_duplicated_val(object_keys, [])
append_val(most_key)
let most_key2 = get_the_most_duplicated_val(object_keys, [most_key])
append_val(most_key2)
if(Object.keys(object_keys).length == 1){
if(last_val() != Object.keys(object_keys)[0]){
append_val(Object.keys(object_keys)[0])
}
for(let i=0;i<object_keys[Object.keys(object_keys)[0]];i++){
rest.push(Object.keys(object_keys)[0])
}
merged_is_completed = true
}
}
console.log("Merged: ", merged)
console.log("Rest: ", rest)
I put it in Codepen so you can test it by yourself :)
https://codepen.io/gofmannir/pen/vYXEmPa?editors=0011
Was an interesting Task, I just wrote a little code it doesn't work perfectly but you can improve it.
const insert = (el, result) => {
if (el !== result.merged[result.merged.length - 1]) {
result.merged.push(el);
if (result.rest.length !== 0) {
for (let i = 0; i < result.rest.length; i++) {
let restItemToInsert = result.rest[i];
if (result.merged[result.merged.length - 1] !== restItemToInsert) {
result.merged.push(restItemToInsert);
result.rest.splice(i, 1);
}
}
}
} else {
result.rest.push(el);
}
return result;
}
const recursive = (arr) => {
let el = arr.shift();
return arr.length === 0 ? { rest: [], merged: [el]} : insert(el, recursive(arr));
}
const testArr = [1, 1, 2, 2, 3, 3, 1, 1, 1];
const testArr2 = [1, 1, 1, 1, 3, 3, 1, 1, 1];
const original = [1,2,2,2,2,2,2,3,4];
console.log(recursive(original));
console.log(recursive(testArr));
console.log(recursive(testArr2));
If you run the code, you should get something like this.
{ rest: [ 2, 2, 2, 2 ], merged: [ 4, 3, 2, 1, 2 ] }
{ rest: [], merged: [
1, 3, 1, 3, 1,
2, 1, 2, 1
] }
{ rest: [ 1, 1, 1, 1 ], merged: [ 1, 3, 1, 3, 1 ] }
You can see, for your const original = [1,2,2,2,2,2,2,3,4]; it doesn't give the right answer. But you can improve it and make it work.
UPDATE
I wrote a better insert function, this should work for any array from your example.
const insert = (el, result) => {
result.rest.unshift(el);
for (let i = 0; i < result.rest.length; i++) {
let restItem = result.rest[i];
for (let j = 0; j < result.merged.length; j++) {
let mergedItem = result.merged[j];
if(mergedItem !== restItem) {
if (result.merged[result.merged.length - 1] !== restItem) {
result.merged.push(restItem);
result.rest.splice(i, 1);
i = -1;
break;
}
if(result.merged[0] !== restItem) {
result.merged.unshift(restItem);
result.rest.splice(i, 1);
i = -1;
break;
}
if (result.merged[j + 1] && result.merged[j + 1] !== restItem) {
result.merged.splice(j + 1, 0, restItem);
result.rest.splice(i, 1);
i = -1;
break;
}
}
}
}
return result;
}

Convert roman number to arabic using javascript

Hi I am trying to convert roman numerals to arabic using javascript. I wrote a code but it is failing.
The rules I am trying to follow are :
if Larger number is before smaller number then addition and if smaller number is before larger number then subtraction.
Along with that I have few other rules as well like 'D','L' and 'V' can't be repeated at all and 'M' can be repeated only twice (Not sure how to implement this, can I use regex for it and how?)
Code :
function romanToArabic(roman){
if(roman == null)
return -1;
var value;
for(var i=0;i<roman.length;i++){
current = char_to_int(roman.charAt(i));
next = char_to_int(roman.charAt(i+1));
console.log("Current",current);
console.log("Next",next);
if(current >= next){
value = current + next;
console.log(value);
}
else {
console.log(value);
value = next - current;
}
}
return value;
}
function char_to_int(character) {
switch(character){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
}
console.log(romanToArabic('IIX'));
Can somebody help? Would appreciate it!
Added screenshots :
To those, who might need to translate conventional roman numbers as opposed to irregular subtractive notation (e.g. 'IIX' instead of 'VIII' for 8), I might suggest my own, slightly shorter method:
const test = ['XIV'/*14*/, 'MXMVI'/*1996*/, 'CII'/*102*/, 'CDI'/*401*/];
const roman2arabic = s => {
const map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000};
return [...s].reduce((r,c,i,s) => map[s[i+1]] > map[c] ? r-map[c] : r+map[c], 0);
};
console.log(test.map(roman2arabic));
.as-console-wrapper {min-height: 100%}
Though, it can be modified to follow unconventional logic:
const test = ['IIV'/*3*/,'XXMMII'/*1982*/, 'IIIXV'/*12*/, 'XII'/*conventional 12*/];
const roman2arabic = s => {
const map = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000};
return [...s]
.reduceRight(({sum,order},c,i,s) =>
Object.keys(map).indexOf(c) < order ?
{sum: sum-map[c], order} :
{sum: sum+map[c], order: Object.keys(map).indexOf(c)},
{sum:0,order:Object.keys(map).indexOf(s[s.length-1])})
.sum;
};
console.log(test.map(roman2arabic));
.as-console-wrapper {min-height: 100%}
The issue is that your code only subtracts the value corresponding to one character, while in IIX you need to subtract twice (although that kind of representation for the number 8 is quite unconventional -- 8 would normally be represented as VIII).
The solution is to keep collecting a separate sum for when the symbol is the same, so that after reading the first two "I", you have two separate sums:
total: 2
value of all "I": 2
Then when you encounter the "X" and detect that a subtraction is needed, you first undo the addition already done for the grand total, and then perform the subtraction with the value you collected for the "I":
total: -2
After this, you start with a reset value for "X":
total: 10 + -2 = 8
value for all "X": 10
Here is your code adapted for that to happen:
function romanToArabic(roman){
if(roman == null)
return -1;
var totalValue = 0,
value = 0, // Initialise!
prev = 0;
for(var i=0;i<roman.length;i++){
var current = char_to_int(roman.charAt(i));
if (current > prev) {
// Undo the addition that was done, turn it into subtraction
totalValue -= 2 * value;
}
if (current !== prev) { // Different symbol?
value = 0; // reset the sum for the new symbol
}
value += current; // keep adding same symbols
totalValue += current;
prev = current;
}
return totalValue;
}
function char_to_int(character) {
switch(character){
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
}
console.log(romanToArabic('IIX'));
As for your additional question to limit the number of consecutive "I" to at most two, "D" at most one, ... you could use a regular expression test at the start of your function:
if (/III|XXX|CCC|MMM|VV|LL|DD|[^IVXLCDM]/.test(roman))
return -1;
You can just append other invalid sub-sequences separated by |. For instance, if you would not want an "I" to appear directly in front of "L", "C", "D" or "M", then extend to:
if (/III|XXX|CCC|MMM|VV|LL|DD|[^IVXLCDM]|I[LCDM]/.test(roman))
return -1;
const romans = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
};
// MXMIV
function roman2arabic(nums){
let sum = 0;
const numsArr = nums.split('');
const isSimpleRoman = (num) => num in romans;
const arabicCompare = (current, prev) => romans[current] < romans[prev];
const orderNums = (acc, current) => {
const prev = acc[acc.length - 1] || null;
const arabCurrent = romans[current];
if (prev && isSimpleRoman(prev) && arabicCompare(current, prev)) {
sum -= arabCurrent;
acc.pop() && acc.push(current + prev);
} else {
sum += arabCurrent;
acc.push(current);
}
return acc;
};
return numsArr.reduceRight(orderNums, []) && sum;
}
const romans = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
};
function roman2arabicRecursion(nums){
const numsArr = nums.split('');
const recursion = (arr, index, sum) => {
const current = arr[index];
const prev = arr[index + 1] || null;
if(prev && romans[current] < romans[prev]){
sum -= romans[current];
} else {
sum += romans[current];
}
if(index === 0) return sum;
return recursion(arr, index - 1, sum);
}
return recursion(numsArr, numsArr.length - 1, 0);
};
Alternatively || operator could be used isntead of ??
const toArabic = (romanNumber) => {
const map = {
M: 1000,
D: 500,
C: 100,
L: 50,
X: 10,
V: 5,
I: 1,
};
const nums = romanNumber.split('');
let result = 0;
for (let i = 0; i < nums.length; i += 1) {
const first = map[nums[i]];
const second = map[nums[i + 1]] ?? 0;
if (first < second) {
result += second - first;
i += 1;
} else {
result += first;
}
}
return result;
};
console.log(toArabic('CMXI')); // 911
console.log(toArabic('MXXIV')); // 1024
We are so used to reading from Left to Right, we overlook the Right to Left alternatives.
The whole point of Roman notation is you want to check if V becomes before X
That is much easier when you reverse the Roman string.
Or in JavaScript, use the hardly ever used reduceRight method
(code optimized for better GZIP/Brotli compression)
const romanToArabic = (input) => [...input].reduceRight((
acc,
letter,
idx,
arr,
value = {m:1000, d:500, c:100, l:50, x:10, v:5, i:1}[letter.toLowerCase()],
doubleSubtraction = letter == arr[idx + 1] // ignore IIX notation
) => {
if (value < acc.high && !doubleSubtraction)
acc.Arabic -= value;
else
acc.Arabic += acc.high = value;
//console.log(idx, letter, acc, 'value:', value, acc.high, arr[idx + 1]);
return acc;
}, { high:0, Arabic:0 }).Arabic; // return Arabic value
//TESTS
Object.entries({
"cxxiv": 124,
"ix": 9,
"iix": 10,
"xL": 40,
"MMMDXLIX": 3549,
"MMMMCMXCIX": 4999}
).map(([roman,value])=>{
let converted = romanToArabic(roman);
console.log(roman, "=", converted);
console.assert(converted == value, "wrong conversion,", roman, "must be", value)
})
I resolved this exercise like this:
function arabic(num) {
let ch;
let sum = 0;
for (let i = 0; i < num.length; i++) {
ch = num[i];
switch (ch) {
case 'I':
if (num[i + 1] === 'V' || num[i + 1] === 'X') {
continue;
}
sum = sum + 1;
break;
case 'V':
if (num[i - 1] === 'I') {
sum = sum + 4;
break;
}
sum = sum + 5;
break;
case 'X':
if (num[i - 1] === 'I') {
sum = sum + 9;
break;
}
if (num[i + 1] === 'C') {
continue;
}
sum = sum + 10;
break;
case 'L':
sum = sum + 50;
break;
case 'C':
if (num[i + 1] === 'D' || num[i + 1] === 'M') {
continue;
}
if (num[i - 1] === 'X') {
sum = sum + 90;
break;
}
sum = sum + 100;
break;
case 'D':
if (num[i - 1] === 'C') {
sum = sum + 400;
break;
}
sum = sum + 500;
break;
case 'M':
if (num[i - 1] === 'C') {
sum = sum + 900;
break;
}
sum = sum + 1000;
break;
}
}
return sum;
}

Javascript: How to find first duplicate value and return its index?

I have to find first duplicate value in array and then return its index in variable firstIndex. This has to be done with for loop which should stop after having found first duplicate. I know this is probably pretty simple but I got stuck. So far I have this but it doesn't seem to be working:
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b])
firstIndex = numbers4.indexOf(numbers4[a]);
break;
}
}
console.log(firstIndex);
Console prints out 1 which is fine because 2 is first duplicate, but when I change numbers in array, the loop doesn't work. Can you advise what can be changed here?
Thanks in advance!
If I correctly understand your question, that's should help you...
Basically, you need for a double iteration.
const firstDupeIndex = list => list.findIndex(
(item, index) => list.lastIndexOf(item) !== index
);
console.log(
"First Dupe at index:",
firstDupeIndex([5, 2, 3, 4, 4, 6, 7, 1, 2, 3])
);
Thee above implementation comes with the drawback of being O(n2), due to nesting the lastIndexOf within the findIndex function.
A better solution would be to index your occurrences by building a dictionary, therefore keeping time complexity to just O(n) in the worst case. Probably a little bit less neat, but surely more efficient with big inputs.
const firstDupeIndex = (list) => {
const dict = {};
for (const [index, value] of list.entries()) {
if (dict.hasOwnProperty(value)) {
return dict[value];
}
dict[value] = index;
}
return -1;
};
console.log(
"First Dupe at index:",
firstDupeIndex(['a', 'b', 'c', 'd', 'e', 'b', 'z', 't', 'c'])
);
Change your code with the following
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
var isMatch=false;
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]){
firstIndex = numbers4.indexOf(numbers4[a]);
isMatch=true;
break;
}
}
if (isMatch) {break;}
}
console.log(firstIndex);
I would use an object remembering the values already found... Something like that should work ;)
var numbers4 = [5, 2, 3, 4, 4, 6, 7, 1, 2, 3];
function findFirstDuplicateIndex(arr){
var found = {};
for (var a = 0, aa = arr.length; a < aa ; a++) {
if (found[arr[a]])
return found[arr[a]];
found[numbers4[a]] = a
}
}
console.log(findFirstDuplicateIndex(numbers4));
It's quite fast because you just loop one time through the array. The rest of the time you just access an object property or you set the object property... Let me know if you have questions ;)
However maybe there something faster... It's just an idea ^^
PS: It also works with words, not just numbers
Your break; terminates b loop, because if() is not using parenthesis {}.
Additionally, firstIndex should be simply set to either a or b depending on whether you need to return the duplicate's first occurance or first repetition.
It should be:
if (numbers4[a] === numbers4[b])
{
firstIndex = a;
break;
}
Your problem is - you have two loops and only one break, you need to break out of both.
Why not simply return the index as soon as values match?
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
function getDuplicate(numbers4)
{
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]){
return a;
}
}
}
}
console.log(getDuplicate(numbers4 ));
However, you can optimize your code further by keeping a map
function getDuplicate( numbers )
{
var map = {};
for (var a = 0; a < numbers.length; a++)
{
if( map[ numbers[ a ] ] )
{
return a;
}
map[ numbers[ a ] ] = true;
}
return -1;
}
You can check if indexOf() is not equal to lastIndexOf() and return value and break loop
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var i = 0; i < numbers4.length; i++) {
if (numbers4.indexOf(numbers4[i]) != numbers4.lastIndexOf(numbers4[i])) {
firstIndex = i;
break;
}
}
console.log(firstIndex)
You don't even need nested for loops.
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 1; a < numbers4.length; a++) { //start from second elem since first is never a duplicate
if (numbers4.lastIndexOf(numbers4[a])> a) {
firstIndex = a;
break;
}
}
console.log(firstIndex); //1
All you have to do during iterating is to check if current value exists somewhere further in array. That is done by checking last index of this value's occurrence using lastIndexOf().
var numbers = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex;
var len = numbers.length;
for (var i = 0; i < len; i++) {
var tmpArray = numbers.slice(i + 1, len);
var index = tmpArray.indexOf(numbers[i]);
if (index !== -1) {
firstIndex = index + i + 1;
break;
}
}
console.log(firstIndex);
Update:
Actually your logic is right, but you missed braces for if condition and also if the condition satisfies then it means firstIndex is the same as a
This is your code with braces,
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 0; a < numbers4.length; a++) {
for (var b = a + 1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]) {
firstIndex = a
break;
}
}
}
console.log(firstIndex);
The question states the first dupe in the array has to be found along with it's index. So I return an object where the i property is the index and the e property is the first duplicate element itself. One way of performing this task would be
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3],
headDupe = (a,r={}) => (r.e = a.find((n,i) => (r.i = a.indexOf(n), r.i < i)),r);
console.log(headDupe(numbers4));

Split string every 3 characters from back using JavaScript

How do we split a string every 3 characters from the back using JavaScript?
Say, I have this:
str = 9139328238
after the desired function, it would become:
parts = ['9','139','328','238']
How do we do this elegantly?
var myString = String( 9139328238 );
console.log( myString.split( /(?=(?:...)*$)/ ) );
// ["9", "139", "328", "238"]
I can't make any performance guarantees. For smallish strings it should be fine.
Here's a loop implementation:
function funkyStringSplit( s )
{
var i = s.length % 3;
var parts = i ? [ s.substr( 0, i ) ] : [];
for( ; i < s.length ; i += 3 )
{
parts.push( s.substr( i, 3 ) );
}
return parts;
}
I know this is an old question, but I would like to provide my own one-line version to solve the problem :)
"12345678".split('').reverse().join('').match(/.{1,3}/g).map(function(x){
return x.split('').reverse().join('')
}).reverse()
This basically reverses the string, captures the groups of 3 elements, reverses each group and then reverses the whole string.
The steps are:
"12345678" -> [1, 2, 3, 4, 5, 6, 7, 8] //.split('')
[1, 2, 3, 4, 5, 6, 7, 8] -> [8, 7, 6, 5, 4, 3, 2, 1] //.reverse()
[8, 7, 6, 5, 4, 3, 2, 1] -> "87654321" //.join('')
"87654321" -> [876, 543, 21] //.match(...)
[876, 543, 21] -> [678, 345, 12] //.map(function(x){...})
[678, 345, 12] -> [12, 345, 678] //.reverse()
You can then join the array with a character (e.g. the ',' for thousands separator)
[12, 345, 678].join(',') -> "12,345,678"
There are a lot of complicated answers here.
function group(value) {
return value.match(/\d{1,3}(?=(\d{3})*$)/g);
}
console.log(group('1'));
console.log(group('123'));
console.log(group('1234'));
console.log(group('12345'));
console.log(group('123456'));
console.log(group('1234567'));
console.log(group('12345678'));
console.log(group('123456789'));
Not as elegant, but shows you a while loop
function commaSeparateNumber (val) {
val = val.toString();
while (/(\d+)(\d{3})/.test(val)){
val = val.replace(/(\d+)(\d{3})/, '$1'+','+'$2');
}
return val;
}
var str = "9139328238";
var splitStr = commaSeparateNumber(str).split(",");
console.log(splitStr);
Try this:
var str = 9139328238 + ''; //convert int to string
var reqArr = []; // required array
var len = str.length; //maintaining length
while (len > 0) {
len -= 3;
reqArr.unshift(str.slice(len)); //inserting value to required array
str = str.slice(0, len); //updating string
}
Hope it helps..
Since regex operations are not liked by everyone for various reasons: here is a regular function using a regular loop to split any regular string every X characters from back. Nothing fancy but it works:
function splitStringFromEnd(customString, every) {
var result = [], counter = every;
// loop that captures substring chungs of "every" length e.g.: 1000.00 -> ["000", ".00"]
for (var i = counter; counter <= customString.length; counter += every) {
result.unshift(customString.substr(customString.length - counter, every))
}
// check if there is a remainder and grabs it.
// Using our 1000.00 example: diff = 9 - 7; remainder = 3 - 2; -> ["1", "000", ".00"]
var diff = counter - customString.length;
var remainder = every - diff;
if(remainder > 0) { result.unshift(customString.substr(0, remainder)) }
return result;
}
for your example it would be:
splitStringFromEnd("9139328238", 3);
// :returns => ["9", "139", "328", "238"]
Enjoy :)
const price_format = (price) => {
let result = [];
let new_str = [...price].reverse().join("");
let rightSplit = new_str.match(/.{1,3}/g).reverse();
for (let item of rightSplit) {
result.push([...item].reverse().join(""));
}
return result.join(",");
}
let price = "2560000000";
console.log(price_format(price));
// output : 2,560,000,000
"12345678".split('').reverse().reduce((a, s) => (a[0].length<3?a[0]=s+a[0]:a.unshift(s),a), ['']);
Finally it seems good. This is what I have got till now without using any loops
function breakAt3(x)
{
if(x.length < 3){ var parts = [x]; return parts; }
var startPos = (x.length % 3);
var newStr = x.substr(startPos);
var remainingStr = x.substr(0,startPos);
var parts = newStr.match(/.{1,3}/g);
if(remainingStr != ''){ var length = parts.unshift(remainingStr); }
return parts;
}
var str = '92183213081';
var result = breakAt3(str); // 92,183,213,081

Categories

Resources