Reputation: 452
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.
Upvotes: 2
Views: 158
Reputation: 24638
(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);
Upvotes: 2
Reputation: 177975
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)
Upvotes: 3
Reputation: 536
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());
Upvotes: 1
Reputation: 2364
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']
Upvotes: 1
Reputation: 198
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);
Upvotes: 1
Reputation: 19986
Please find your issue fixed below.
Logic
uniqueData
.uniqueValues
push the value from array2
to uniqueData
.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);
Upvotes: 2
Reputation: 1298
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
})
Upvotes: 0
Reputation: 159
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);
Upvotes: 2