2

I need some help to sum values inside an array in order

I have two arrays:

array1 = ['car', 'car', 'ball', 'piano', 'car'] 
array2 = ['2500', '1000', '400', '2500', '4500']

I'm using this code below to remove the duplicated values inside array1:

var uniqueValues = [];
for(var i in array1){
    if(uniqueValues.indexOf(array1[i]) === -1){
       uniqueValues.push(array1[i]);
    }
}

//returns ['car', 'ball', 'piano'] 

What I need is to sum the values of array2 using the order of array1, so I will have this result:

result = ['8000', '400', '2500']

So the final result would be this:

array1 = ['car', 'ball', 'piano'] 
array2 = ['8000', '400', '2500']

Any suggestion ? thank you.

8
  • 2
    Try combining the arrays first, then filtering, then summing? Commented Sep 13, 2021 at 14:01
  • 1
    Do the summing in an object whose keys are the names. Then get the object's keys and values to get the result array. Commented Sep 13, 2021 at 14:04
  • Do they really need to be in the original order? Shouldn't it be enough that the two result arrays are in consistent order with each other? Commented Sep 13, 2021 at 14:05
  • 1
    Can try searching for "JavaScript group by and sum" examples. Then apply those to your scenario Commented Sep 13, 2021 at 14:05
  • 1
    @0stone0 You're just handing out code, at best with a one-line explanation. Don't give people a free fish, teach them how to fish. At least that's how this website is supposed to work, afaik. Commented Sep 13, 2021 at 14:11

8 Answers 8

3

Reduce will do the trick

NOTE Does JavaScript guarantee object property order?

let array1 = ['car', 'car', 'ball', 'piano', 'car'] 
let array2 = ['2500', '1000', '400', '2500', '4500']

const merged = array1.reduce((acc,cur,i) => {
  acc[cur] = (acc[cur] || 0) + +array2[i]; // add after casting to number
  return acc
},{})

console.log(merged)

array1 = Object.keys(merged)
array2 =  Object.values(merged)

console.log(array1)
console.log(array2)

Sign up to request clarification or add additional context in comments.

2 Comments

I don't know. Your answer is by far the best! (I +1)
@mplungjan Yep like mine. Like your use of the ||. Cleaner than my use of an if statement.
2

You can use a Map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

If the number values are Strings like in your example, you also need to cast them to numbers first.

array1 = ['car', 'car', 'ball', 'piano', 'car']
array2 = [2500, 1000, 400, 2500, 4500]

var map = new Map();

for (var i = 0; i < array1.length; i++) {
  var mapval = map.get(array1[i]);
  if (mapval == null) mapval = 0;
  mapval += array2[i];
  map.set(array1[i], mapval)
}

function logMapElements(value, key, map) {
  console.log(`m[${key}] = ${value}`);
}
map.forEach(logMapElements);

2 Comments

@mplungjan the code works, but you can not do console.log(map). You can paste it into your browser console and see the results. I added a console.log to the example.
Still it does not answer OPs question to set the two arrays
2

Please find your issue fixed below.

Logic

  • Create a new array to hold the sum of values called uniqueData.
  • While pushing data to uniqueValues push the value from array2 to uniqueData.
  • If the node already exist, update the sume value.

const array1 = ['car', 'car', 'ball', 'piano', 'car'] 
const array2 = ['2500', '1000', '400', '2500', '4500']

const uniqueValues = [];
const uniqueData = [];
for(var i in array1) {
  const index = uniqueValues.indexOf(array1[i]);
    if(index === -1){
      uniqueValues.push(array1[i]);
      uniqueData.push(array2[i]);
    } else {
      uniqueData[index] = (+uniqueData[index] + +array2[i]).toString()
    }
}

console.log(uniqueValues);
console.log(uniqueData);

Please find Array.reduce implementation of your requirement below. You can find the description as the code comment.

//Your dataset
const array1 = ['car', 'car', 'ball', 'piano', 'car'];
const array2 = ['2500', '1000', '400', '2500', '4500'];

// Array to hold the sum from array2
const uniqueData = [];

// Array to hold the aggrigate of array1
const uniqueValues = array1.reduce((acc, curr, itration) => {
  // acc: accumulator
  // curr: current node
  // itratiion: index of each node from array1

  // if the node is already present in accumulator
  // Dont push it to accumulator
  // Instead update the sume value in uniqueData array
  const index = acc.indexOf(curr);
  if(index === -1) {
    // Node is not there in accumulator
    // Then push to accumulator
    acc.push(curr);
    // Push the value in the index `itration` from `array2` to `uniqueData` array
    uniqueData.push(array2[itration])
  } else {
    // If the node is found update the data in uniqueData array
    // as the numeric sume of the value in that index and the value from array2
    uniqueData[index] = (+uniqueData[index] + +array2[itration]).toString()
  }
  return acc;
}, []); 
console.log(uniqueValues);
console.log(uniqueData);

Comments

2

(1) Use Array#reduce() and Object.assign() to build an object with unique keys (and values summed):

{ car: 8000, ball: 400, piano: 2500 }

(2) Use Object.keys() to get new array1:

[ 'car', 'ball', 'piano' ]

(3) Use Object.values() to get new array2:

[ 8000, 400, 2500 ]

DEMO 1

let array1 = ['car', 'car', 'ball', 'piano', 'car'];
let array2 = ['2500', '1000', '400', '2500', '4500'];

const result = array1.reduce((acc, cur, index) => Object.assign(acc, {
    [cur]: (acc[cur] || 0) + +array2[index]
}), {});

array1 = Object.keys(result);
array2 = Object.values(result);

console.log(array1);
console.log(array2);

You can also return an object literal directly in Array#reduce() as follows:

const result = array1.reduce((acc, cur, index) => ({
    ...acc,
    [cur]: ((acc[cur] || 0) + +array2[index])
}), {});

DEMO 2

let array1 = ['car', 'car', 'ball', 'piano', 'car'];
let array2 = ['2500', '1000', '400', '2500', '4500'];

const result = array1.reduce((acc,cur,index) => ({...acc,[cur]:((acc[cur] || 0) + +array2[index])}), {});

array1 = Object.keys(result);
array2 = Object.values(result);

console.log(array1);
console.log(array2);

Comments

1

You can use a for each (this scenario applies if both arrays are same length)

let array1 = ['car', 'car', 'ball', 'piano', 'car'];
let array2 = ['2500', '1000', '400', '2500', '4500'];

const result = {};
array1.forEach((item, i) => {
  if (!result[item]) {
    result[item] = 0;
  }
  result[item] += Number(array2[i])
});

array1 = Object.keys(result); // ['car', 'ball', 'piano']
array2 = Object.values(result); // [8000, 400, 2500]

console.log(array1);
console.log(array2);

Comments

1

array1 = ['car', 'car', 'ball', 'piano', 'car'];
array2 = ['2500', '1000', '400', '2500', '4500'];

///Get unique values

var uniqueValues = [];
for (var i in array1) {
  if (uniqueValues.indexOf(array1[i]) === -1) {
    uniqueValues.push(array1[i]);
  }
}

var uniqueSums = [];

///Cycle through all items in original array

var _ind = 0;
array1.forEach(function(element) {

  //get associated value from second array 

  let _var = parseFloat(array2[_ind]);

  //Add value to total value in sum array

  let _uniqueInd = uniqueValues.indexOf(element);
  if (undefined != uniqueSums[_uniqueInd]) uniqueSums[_uniqueInd] = uniqueSums[_uniqueInd] + _var;
  else uniqueSums[_uniqueInd] = _var;
  _ind++;
});

//override org arrays
array1 = uniqueValues;
array2 = uniqueSums;

console.log(array1);
console.log(array2);

//will result:
//['car', 'ball', 'piano'] 
//['8000', '400', '2500']

1 Comment

I've created a snippet for you. Maybe you could improve your answer by adding some details. As shows here: How to Answer; code-only answers are discouraged.
1

Not exactly the best solution, but should work. I have used the map to create an index and add the values. It is a simple one.

let array1 = ['car', 'car', 'ball', 'piano', 'car', 'ball', 'piano'];
let array2 = ['2500', '1000', '400', '2500', '4500', '2500', '4500'];
const MapOfItems = new Map();
array1.forEach(function(item, index) {
  if (MapOfItems.has(item))
    MapOfItems.set(item, MapOfItems.get(item) + +array2[index]);
  else
    MapOfItems.set(item, +array2[index]);
});

console.log(MapOfItems);
console.log(MapOfItems.keys());
console.log(MapOfItems.values());

Comments

0

Here is how to do it with reduce.

const array1 = ['car', 'car', 'ball', 'piano', 'car']
const array2 = ['2500', '1000', '400', '2500', '4500']

const result = array1.reduce((a, word, index) => {
  if (!a[word]) a[word] = 0;
  a[word] += Number(array2[index]);
  return a
}, {});

const [keys, values] = [
  Object.keys(result),
  Object.values(result)
];

console.log({
  keys
}, {
  values
})

5 Comments

That is only part one of my answer
@mplungjan No, it filters and adds them, so it does both parts. Run it and see.
Please see my answer. OP said: So the final result would be this: array1 = ['car', 'ball', 'piano'] array2 = ['8000', '400', '2500']
@mplungjan Thought you would know how to destructure an object. I updated it anyway.
Yes I know, but it was missing from yours and you are not rewriting array 1 and 2 - you cannot destruct if they are already defined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.