Sum similar keys from string array

Hi

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

Code:

a:3, s:4, v:7

how I can do that ?

This looks like homework, so actual answers in terms of working code are to be discouraged.

One solution is to sort, reduce, filter

  • sort: sort the array so that it’s sorted by the key
  • reduce: use the reduce method so that when an item has the same key as a previous item, you add the value from that previous one on to the current one
  • filter: find the last index of an item with that key, and if it’s the same index as the item being filtered, then keep it
1 Like

but the problem the array has both key and value inside “” so I need to remove quotation first ?

That is where the split method becomes very useful.

1 Like

Thanks will try to figure it out.

think theres a bit of data cleaning to be done first, Paul, as the input array as given doesnt actually have keys, its just an array of strings.

Looks more like the assignment would expect a foreach solution.

You can do it very easy with some really 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 can be done, 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']

That would need a whole 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 into an array.

Sum 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 props to an Array

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 could combine the two within 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 alot guys I learned many useful things

1 Like

Why -2 ?

arr.length-2

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 string array becomes ["a:3", "s:4", "v:2", "v:5"]. On the first loop of the ‘for’ loop the keys keyz and keyz1 will both have string value “v”. The long line of code then sums the values of the two keys and updates the penultimate element with the new value: so the penultimate element becomes “v:7”. The last element of the array (“v:5”) is then deleted. So we can say the last two array elements have been ‘merged’ (my terminology).

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

If the array is changed to, 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 differ so the ‘if’ conditional block will not be executed. In the third loop keyz and keyz1 will both be “s” so the array elements will be ‘merged’.

The code will ‘merge’ array elements if more than two elements have the same key.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.