Adding numeric values in a string together

Viewed 105

I have a string returned from an endpoint in which I need to add certain parts of the string together in order to produce two different values.

Example response:

149,226;147,226;146,224

Now I know I can use the unary plus operator to force the string to be treated as a number like so.

var num1 = '20',
    num2 = '22';

var total = (+num1) + (+num2);

or I could do some conversion like so

   var number1 = parseInt(num1);
   var number2 = parseInt(num2);

   var total = number1  + number2;

either of these work fine however this is not what I am looking for exactly.

I want to take this result

149,226;147,226;146,224

Then add all the numbers before the first comer together so that would be (149, 147, 146) to produce one result and then add all the number after the second comer together (226, 226, 224).

I know I probably need some sort of reg expression for this I just dont know what.

6 Answers

You can just use string.split, twice, one for the ; and then again for the ,. And put this through array.reduce.

eg.

var str = '149,226;147,226;146,224';


var result = str.split(';')
  .reduce((a,v) => {
    var vv = v.split(',');
    a[0] += vv[0] | 0;
    a[1] += vv[1] | 0;
    return a;
  }, [0, 0]);
  
console.log(result);

For a more generic solution, that could handle any number of sub strings, eg. 1,2,3;4,5,6, and also handle alternative split types, and cope with extra , or ;.

function sumStrings(str, outerSplit, innerSplit) {
  return str.split(outerSplit || ';')
    .filter(Boolean)
    .reduce((a,v) => {
      v.split(innerSplit || ',')
        .filter(Boolean)
        .forEach((v,ix) => {
          a[ix] = (a[ix] | 0) + (v | 0);
        });
      return a;
    }, []);      
}

console.log(sumStrings(
  '149,226;147,226;146,224'
));
  
console.log(sumStrings(
  '149.226.201|147.226.112.|146.224.300|',
  '|','.'));
  
//how about total of totals?
console.log(sumStrings(
  '149,226;147,226;146,224'
).reduce((a,v) => a + v));
.as-console-wrapper {
  min-height: 100%
}

without using regex, one possible solution:

var c = '149,226;147,226;146,224'
var d = c.split(";")
var first = d.map(x=>Number(x.split(",")[0]))
var second= d.map(x=>Number(x.split(",")[1]))
console.log(first)
console.log(second)

let resultFirst = first.reduce((a,b) => a + b, 0);
let resultSecond = second.reduce((a,b) => a + b, 0);
console.log(resultFirst)
console.log(resultSecond)

You could do:

const myString = '149,226;147,226;146,224';

/*
 * 1. you split the string by ';' to obtain an array of string couples
 *    then you split each couple by ','. In this way you end up with an array like this:
 *    [['149', '266'], ['147', '266'], ['146', '264']]
 */
const myNumbers = myString.split(';').map(numCouple => numCouple.split(','));

/*
 * 2. you use Array.prototype.reduce() to calculate the sums
 */
const sum1 = myNumbers.reduce((sum, item) => {
  return sum += parseInt(item[0]);
}, 0);
const sum2 = myNumbers.reduce((sum, item) => {
  return sum += parseInt(item[1]);
}, 0);

// or, as an alternative:
const sumsObj = myNumbers.reduce((obj, item) => {
  obj.sum1 += parseInt(item[0]);
  obj.sum2 += parseInt(item[1]);
  return obj;
}, { sum1: 0, sum2: 0 });

// or also:
const sumsArr = myNumbers.reduce((acc, item) => {
  acc[0] += parseInt(item[0]);
  acc[1] += parseInt(item[1]);
  return acc;
}, [0, 0]);


// test
console.log('sum1:', sum1);
console.log('sum2:', sum2);
console.log('--------------');
console.log('sum1:', sumsObj.sum1);
console.log('sum2:', sumsObj.sum2);
console.log('--------------');
console.log('sum1:', sumsArr[0]);
console.log('sum2:', sumsArr[1]);

Below supplies regex to String's .split to get the numbers by themselves. Then you could add every other number but I don't see why not just add them all in order.

const str = '149,226;147,226;146,224'

const total = str.split(/[;,]/).map(Number).reduce((a, b) => a + b)

console.log('total', total)

I got this one running:

const nums = ('149,226;147,226;146,224');
var firstNums = nums.match(/(?<=[0-9]*)[0-9]+(?=,)/gs);
var secondNums = nums.match(/(?<=[0-9]*)[0-9]+(?=;|$)/gs);
console.log(firstNums, secondNums);
let sumFirstNums = 0,  
    sumSecondNums = 0;
firstNums.map(x => {
  sumFirstNums += +x;
})
console.log(sumFirstNums)

secondNums.map(x => {
  sumSecondNums += +x;
})
console.log(sumSecondNums)

//If you want the result in the same format: 
const finalResult = `${sumFirstNums}, ${sumSecondNums};`
console.log(finalResult)

;)

For that string format, you could use a single pattern with 2 capturing groups matching 1+ more digits between a comma, and asserting a ; or the end of the string at the right.

You refer to the group values by indexing into the match of every iteration.

(\d+),(\d+)(?=;|$)

The pattern matches

  • (\d+) Capture group 1, match 1+ digits
  • , Match a comma
  • (\d+) Capture group 2, match 1+ digits
  • (?=;|$) Positive lookahead, assert directly to the right a ; or end of the string

See a regex demo.

let result1 = 0;
let result2 = 0

for (const match of "149,226;147,226;146,224".matchAll(/(\d+),(\d+)(?=;|$)/g)) {
  result1 += +match[1]
  result2 += +match[2]
}

console.log(result1, result2);

Related