Sum similar keys from an array of strings – JavaScript – SitePoint Forums

Hi

I have this string array form [“v:2”, “a:3”, “v:5”, “s:4”] I need to sum similar keys, also sort keys and output in this form

Coded:

a:3, s:4, v:7

how can i do that?


This looks like a homework assignment, so actual answers in terms of working code should be discouraged.

One solution is to sort, reduce, filter

  • sort: sorts the array so that it is sorted by key
  • reduce: use the reduce method so that when an element has the same key as a previous element, you add the value of that previous one to the current one
  • filter: find the last index of an element with this key, and if it is the same index as the filtered element, keep it



1 like

but the problem, the array has both key and value inside “”, so i have to remove the quote first?

This is where the splitting method becomes very useful.



1 like

Thank you will try to understand.

Think there’s a bit of data cleaning to do first, Paul, because the input array as given doesn’t actually have any keys, it’s just an array of strings.

Looks more like the mission would expect a solution foreach.

You can do this very easily with very bad code :slight_smile:

const arr = [ "v:2", "a:3", "v:5", "s:4" ];

arr.sort();

let lastKey = null;
let result = [];
let value = 0;
for(let str of arr)
{
    let parts = str.split(':');
    if(parts.length !== 2)
         continue;
    if(!lastKey || parts[0] !== lastKey)
    {
       if(lastKey)
           result.push(lastKey+":"+value);
       lastKey = parts[0];
       value = 0;
    }
    value += parseInt(parts[1]);
}
if(lastKey)
	result.push(lastKey+":"+value);

console.log(result);



2 likes

Well, it’s possible, but I don’t like it.

const arr = ["v:2", "a:3", "v:5", "s:4"];

const add = (item, index, arr) => (index === 0 && item) || (arr[index - 1][0] === item[0] && item[0] + ":" + (Number(arr[index - 1][2]) + Number(item[2]))) || item;
const lastOfType = (item, index, arr) => index === arr.length-1 || index < arr.length-1 && arr[index+1][0] !== item[0];

arr.sort();
const totals = arr.map(add).filter(lastOfType);

console.log(totals); // ['a:3', 's:4', 'v:7']

It would require a lot more structure to help make sense of things.

My approach was similar to a post the other day with two functions, one to total and one to convert back to an array.

Sum of values

const sumKeyValues = function(values) {

  const totals = {};
  
  for (item of values) {
    const [key, value] = item.split(':');

    if (totals[key] === undefined) totals[key] = 0;

    totals[key] += Number(value);
  }
  return totals;
}

// Example
sumKeyValues(['f:2', 'f:3', 'a:1'])
// { f: 5, a: 1 }

Object accessories to a board

const propsToArray = function(props) {
  return Object
    .entries(props)
    .map(([key, value]) => `${key}:${value}`)
    .sort();
}

// Example
propsToArray({z: 1, b: 3, e: 5})
// ["b:3","e:5","z:1"]

Combined

const values = ['v:2', 'a:3', 'v:5', 's:4', 'a:4', 'z:1'];

// call one function on the result of another
const result = propsToArray(sumKeyValues(values));

console.log(result)
// ["a:7","s:4","v:7","z:1"]

Alternatively, you can combine the two in sumKeyValues

const sumKeyValues = function(values) {

  const totals = {};
  
  for (item of values) {
     ... same as before
  }
  // call propsToArray on result and return
  return propsToArray(totals);
}

sumKeyValues(values) // ["a:7","s:4","v:7","z:1"]



1 like

How about this simple approach?

const arr = ["v:2", "a:3", "v:5", "s:4"];
arr.sort();    // do this first !
for (let z=arr.length-2 ; z>=0 ; z--){     // working backwards through array
	let keyz  = arr[z].split(":")[0];
	let keyz1 = arr[z+1].split(":")[0];

	if(keyz == keyz1){     // if keys are the same ....
		arr[z] = keyz + ":" + (parseInt(arr[z].split(":")[1]) + parseInt(arr[z+1].split(":")[1]));   // sum values and update first array element
		arr.splice(z+1,1);   // delete second array element.
	}
}



2 likes

Thanks a lot guys I learned a lot of useful things



1 like

Initially arr.length-2 is the index of the penultimate element of the array, so arr[z] is the penultimate string element and arr[z+1] is the last string element of the array.

After arr.sort() the array of strings becomes ["a:3", "s:4", "v:2", "v:5"]. On the first loop of the ‘for’ loop the keys keyz and keyz1 both will have the string value “v”. The long line of code then adds the values ​​of the two keys and updates the penultimate element with the new value: thus the penultimate element becomes “v:7”. The last element of the array (“v:5”) is then deleted. So we can say that the last two elements of the array have been “merged” (my terminology).

On the next loop of the ‘for’ loop keyz will be “a” and keyz1 will be “v” so that the code in the “if” condition block is not executed. Likewise for the next loop, which will be the final loop.

If the array is replaced by, for example, ["v:2","s:12", "a:3", "v:5", "s:4"]after the sort() it will become ["a:3", "s:4", "s:12", "v:2", "v:5"]. The first loop of the ‘for’ loop will work as before and the two elements will be ‘merged’. In the second loop keyz and keyz1 will be different so that the conditional ‘if’ block is not executed. In the third loop keyz and keyz1 will both be “s” so that the array elements are “merged”.

The code will “merge” array elements if more than two elements have the same key.



1 like

Comments are closed.