If I have two objects in javascript such that object a
let relative_weight = {
"Composure": 0.175,
"Build": 0.128,
"Strategic": 0.096,
"Career": 0.079,
"Change": 0.062,
"Participative": 0.059,
"SelfAware": 0.055,
"Leading": 0.048,
"Taking": 0.047,
"Balance": 0.041,
"Putting": 0.041,
"Compassion": 0.039,
"Decisive": 0.037,
"Respect": 0.033,
"Quick": 0.031,
"Confront": 0.028
}
and object b
let values = {
Strategic: 1,
Decisive: 1,
Quick: 1,
Change: 1,
Leading: 1,
Confront: 1,
Build: 1,
Compassion: 1,
Putting: 1,
Respect: 1,
Taking: 1,
Composure: 1,
Balance: 1,
SelfAware: 1,
Career: 1,
Participative: 1
}
How can I multiple values in object a and b and then sum the results to produce a single value?
I looked up on SO, but didn't really find much that could help me; at least I couldn't tell what to do with those that I found. I did try some, but didn't work. Then, I realized, the one that I tried was a solution for python because I search for the term dictionary. I'm bit lost on how to do this in JavaScript.
const sums = []
for (let [key, value_a] of Object.entries(relative_weight)) {
let value_b = values[key]
sums.push(value_a * value_b)
}
console.log(sums.reduce((accum, current) => accum + current))
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
This is very simple. Find the keys of the objects. You could start by assuming that the set of keys is identical (but you should confirm this assumption), then iterate through the keys and accumulate the sum of the product.
let values = {Strategic:1,Decisive:1,Quick:1,Change:1,Leading:1,Confront:1,Build:1,Compassion:1,Putting:1,Respect:1,Taking:1,Composure:1,Balance:1,SelfAware:1,Career:1,Participative:1}
let relative_weight = {"Composure":0.175,"Build":0.128,"Strategic":0.096,"Career":0.079,"Change":0.062,"Participative":0.059,"SelfAware":0.055,"Leading":0.048,"Taking":0.047,"Balance":0.041,"Putting":0.041,"Compassion":0.039,"Decisive":0.037,"Respect":0.033,"Quick":0.031,"Confront":0.028 }
let result = 0
for (let key of Object.keys(values)) {
// assumes that both maps hold the same keys, if either doesn't 0 will be added
result += values[key] * relative_weight[key]
}
console.log(result)
This is actually logically equivalent to using the Array .reduce() method:
console.log(Object.keys(values).reduce((accumulator, currentValue) => accumulator + values[currentValue] * relative_weight[currentValue], 0))
You can loop objects with for(.. in ..)
const relativeWeight = {
"Composure": 0.175,
"Build": 0.128,
"Strategic": 0.096,
"Career": 0.079,
"Change": 0.062,
"Participative": 0.059,
"SelfAware": 0.055,
"Leading": 0.048,
"Taking": 0.047,
"Balance": 0.041,
"Putting": 0.041,
"Compassion": 0.039,
"Decisive": 0.037,
"Respect": 0.033,
"Quick": 0.031,
"Confront": 0.028
}
const values = {
Strategic: 1,
Decisive: 1,
Quick: 1,
Change: 1,
Leading: 1,
Confront: 1,
Build: 1,
Compassion: 1,
Putting: 1,
Respect: 1,
Taking: 1,
Composure: 1,
Balance: 1,
SelfAware: 1,
Career: 1,
Participative: 1
}
function multiplyObjects(objA, objB){
const outputObj = {};
for(prop in objA){
outputObj[prop] = objB[prop] * objA[prop];
}
return outputObj;
}
function sumArray(arr){
return arr.reduce((acc, val) => acc+val, 0);
}
console.log('functional programming version:', sumArray(Object.values(multiplyObjects(relativeWeight, values))));
// or you can only use a single loop for both multiply and add:
function operateOnObjects(objA, objB, operationFn){
const outputObj = {};
for(prop in objA){
outputObj[prop] = operationFn(objB[prop], objA[prop]);
}
return outputObj;
}
function multiplyAndAddObjects(objA, objB){
let sum = 0;
let multipliedOutput = operateOnObjects(relativeWeight, values, (a,b) => {
sum += a*b;
});
return sum;
}
console.log('single loop:', multiplyAndAddObjects(relativeWeight, values));
// to solve the precision error, multiply to ensure it is not a floating
// point number and then divide by the same afterwards
function customMultiplyAndAddObjects(objA, objB){
let sum = 0;
const sfAmount = 1000;
let multipliedOutput = operateOnObjects(relativeWeight, values, (a,b) => {
sum += a*sfAmount*b;
});
return sum / sfAmount;
}
console.log('precision fixed:', customMultiplyAndAddObjects(relativeWeight, values));
This is cleaner than for(.. of ..) which would require you to first convert the object to an array, for example with Object.entries(obj).
Related
I have a JSON in which I save the GuildID and then again the UserID
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
Now I want to sort the users by XPIns from one Guild. I remember this code part here
let obj;
fs.readFile('./xpdata.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data)
var sorted = Object.entries(obj).sort((a, b) => b[1] - a[1])
});
In the end, the user with more should be in the 1st position (866935358448468008). Can anyone help me?
I've seen a similar question before but couldn't get it to work if there was a GuildID in front of it
The code I had done before (sorry for the sloppy code that was a year ago (Code is updated)):
let obj;
fs.readFile('./userdata.json', 'utf8', function (err, data) {
if (err) throw err;
try {
obj = JSON.parse(data)
} catch (error) {
if(error) return console.log("Ein Fehler ist aufgetreten! " + error);
}
var sorted = Object.entries(obj).sort((a, b) => b[1].Economy.Balance - a[1].Economy.Balance)
if(sorted.length > 10) sorted = sorted.slice(0, 10)
var lBString = "";
var s = 1;
sorted.forEach(user => {
let usertag = Data[user[0]].Tag
lBString += `${s}. ${usertag} • **${user[1].Economy.Balance}$**\n`
s = s += 1
})
let embed = {
title: `Leaderboard Balance`,
description: lBString,
color: 0xFFFF00,
thumbnail: {
url: client.user.avatarURL(),
},
timestamp: new Date(),
footer: {
text: footer,
icon_url: client.user.avatarURL(),
},
}
e.reply({embeds: [embed]});
});
If you simply want the highest ranking user in terms of "XPIns", I suggest you use a Array.reduce() call on the entries of the inner object.
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
const topUser = Object.entries(data['385524088980111362']).reduce((acc, cur) => (
acc[1]?.XPIns > cur[1]?.XPIns ? acc : cur
), []);
console.log(topUser);
What I do in cases like this is to use another object as index using a reference of the main array/object
ie:
var index = {};
// replace .id with the attribute you want to use. In your case XPins
index[ object.id ] = main_index_reference;
once you have generated the index, then you can get the keys using Object.keys( index ):
var keys = Object.keys( index );
keys.forEach( function( key ){
var element = main_object[ key ];
// do whatever with the element
} );
Your main_object remains unchanged. In your particular case you want the highest value, all you need to do is to extract the last element from the keys array.
You can try with this. However, the users do not have their ID inside their object, so you'd probably have to patch the ID before sorting.
const data = {
// if the guild could have list of users then it would have been much better
// instead of Object list with ID, Array of objects with ID in it works much faster..
"385524088980111362": {
"672748733737467936": {
// if we had user ID here, then it would have been better
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
function getSortedUsersByXPins(data, guildId) {
// if guild has array of users, then we won't need Object.values
const sorted = Object.values(data[guildId]).sort((user1, user2) => {
return user2.XPins - user1.XPins
});
return sorted;
}
const sorted = getSortedUsersByXPins(data, '385524088980111362');
console.log(sorted)
You can try it with this solution, in case you want to convert the object to a list. The main issue is the missing identifier if you work with a list.
This assumes that you would use a function like Object.entries before to convert it.
My recommendation: Include the id into the object and convert it to a list.
let guildList = [
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2,
"Id": "672748733737467936"
},
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7,
"Id": "866935358448468008"
}
];
let aSorted = guildList.sort((a, b) => b.XPIns-a.XPIns)
console.log(aSorted)
Just extract the player objects and sort them, pretty much the way you already described ((p1, p2) => p2.XPIns - p1.XPIns).
Here is an example:
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
}
const res = Object.fromEntries(Object.entries(data).map( ([gid, users]) => [gid, Object.entries(users).map(([id, u]) => ({id, ...u })).sort( (u1, u2) => u2.XPIns - u1.XPIns)] ))
console.log(res)
Note that you cannot create an object with player id as key without losing the order, since JS objects always put numeric keys in ascending order.
How I solve this in the most efficient way? Should we work with .reduce() and these methods or should we use the classic for in loop to iterate over the keys in allStore and calculate it with the recipe?
var soup = { //recipe
potato: 3,
onion: 1,
corn: 5
};
var edoka = {
cheese: 8,
corn: 3,
meat: 6,
onion: 4,
pea: 1,
oregano: 7,
potato: 5,
tomato: 6
};
var were = {
cheese: 6,
corn: 2,
meat: 9,
onion: 5,
pea: 2,
oregano: 6,
potato: 3,
tomato: 3
};
var brutto = {
cheese: 6,
corn: 2,
meat: 9,
onion: 5,
pea: 2,
oregano: 8,
potato: 3,
tomato: 4
};
var allStores = { // this is an example of a "storeCollection"
Brutto: brutto,
Edoka: edoka,
Were: were,
};
function cheapestStoreForRecipe(recipe, storeCollection){
// make it return the key for the store in storeCollection
// that has the cheapest total cost for recipe. Feel free
// to use costOfRecipe inside this function!
}
This is the most efficient way to solve your problem:
function cheapestStoreForRecipe(recipe, storeCollection) {
let cheapestStore;
let cheapestPrice = Number.MAX_SAFE_INTEGER;
Object.keys(storeCollection).forEach(store => {
let costOfRecipe = 0;
Object.keys(recipe).forEach(ingredient => {
costOfRecipe += recipe[ingredient] || 0;
});
if (costOfRecipe < cheapestPrice) {
cheapestPrice = costOfRecipe;
cheapestStore = store;
}
});
return cheapestStore;
}
Some argue that for is more efficient than forEach. Others say this is no longer true, in mordern environments. I prefer the forEach implementation for readability.
Here is a solution that will help you explore how to use Array.reduce. It may not be the most efficient, but from here you can devise your own solution. To make this more efficient, you should continue working with the concept to get the results you need in terms of processing time or complexity.
Repl Example
cheapestStoreForRecipe accepts two arguments: recipe and storeCollection. The method returns a list of stores with invoices for the recipe that includes the cost of each item and total cost.
First, storeCollection iterates through each store in the collection. Second, for each store the recipe items are iterated through. When there is a recipe item that matches a store inventory item, the quantity, unit, and total values for the item are calculated; then the total cost of each recipe is calculated.
function cheapestStoreForRecipe(recipe, storeCollection){
return Object.entries(storeCollection)
.reduce((_storeCollection, [storeName, storeInventory]) => {
let storeInvoice = Object.entries(recipe)
.reduce((_recipe, [itemName, itemQuantity]) => {
let storeInventoryItem = storeInventory[itemName]
if(storeInventoryItem) {
_recipe.invoice[itemName] = {
quantity: itemQuantity,
unit: storeInventoryItem,
total: itemQuantity * storeInventoryItem,
}
_recipe.total += _recipe.invoice[itemName].total
}
return _recipe
}, {
invoice: {},
total: 0,
})
_storeCollection[storeName] = storeInvoice
return _storeCollection
}, {
Brutto: {},
Edoka: {},
Were: {},
})
}
{
"Brutto": {
"invoice": {
"potato": {
"quantity": 3,
"unit": 3,
"total": 9
},
"onion": {
"quantity": 1,
"unit": 5,
"total": 5
},
"corn": {
"quantity": 5,
"unit": 2,
"total": 10
}
},
"total": 24
},
"Edoka": {
"invoice": {
"potato": {
"quantity": 3,
"unit": 5,
"total": 15
},
"onion": {
"quantity": 1,
"unit": 4,
"total": 4
},
"corn": {
"quantity": 5,
"unit": 3,
"total": 15
}
},
"total": 34
},
"Were": {
"invoice": {
"potato": {
"quantity": 3,
"unit": 3,
"total": 9
},
"onion": {
"quantity": 1,
"unit": 5,
"total": 5
},
"corn": {
"quantity": 5,
"unit": 2,
"total": 10
}
},
"total": 24
}
}
I would go for this personally, it's the most readable IMO (although that is subjective obviously). I would expect the performance to as good as any and a it's a good chance to use the fairly new Object.entries API.
function cheapestStoreForRecipe(recipe, storeCollection){
let cheapest, cheapestStore;
for (const [storeName, store] of Object.entries(allStores)) {
let total = 0;
for (const [ingredient, amnt] of Object.entries(recipe)) {
total += store[ingredient] * amnt;
}
if (!cheapest || total < cheapest) {
cheapest = total;
cheapestStore = storeName;
}
}
return cheapestStore;
}
To calculate the cost of a recipe you'll need to sum the values of an array made of the intersection of recipe keys and each store products keys. But that's your homework and you must do it yourself.
Regarding the efficiency of different ways to sum the elements of an array, for is the most efficient in long arrays.
I made a small demo below comparing
for
for..of
forEach
reduce
const add = (a, b) => a + b;
const functionsObj = {
usingFor: async(array) => {
return new Promise(res => {
let result = 0;
for (let i = 0; i < array.length; i++) {
result += array[i];
}
res(result);
});
},
usingForeach: async(array) => {
return new Promise(res => {
let result = 0;
array.forEach(number => {
result += number;
})
res(result);
});
},
usingReduce: async(array) => {
return new Promise(res => {
const result = array.reduce(add);
res(result);
});
},
usingForOf: async(array) => {
return new Promise(res => {
let result = 0;
for (let i of array) {
result += i;
}
res(result);
});
}
};
const Arr10M = [];
for (let j = 0; j < 10000000; j++) {
Arr10M.push(
1 + parseInt(40 * Math.random(), 10)
);
}
const Arr10K = Arr10M.slice(0, 10000);
async function runTests(method, arr, attempts = 300) {
let results = [];
for (let attempt of arr.slice(0, attempts)) {
performance.mark('start');
await functionsObj[method](arr);
performance.mark('end');
results.push(performance.measure(method, 'start', 'end').duration);
performance.clearMeasures();
performance.clearMarks();
}
return new Promise(res => {
let min = 1 * Number(Math.min(...results)).toFixed(6),
max = 1 * Number(Math.max(...results)).toFixed(6);
window.setTimeout(() => {
res([min, max]);
}, 1000 - 1 * max);
});
}
(async() => {
let results = {},
methods = ['usingFor', 'usingForOf', 'usingReduce', 'usingForeach'];
for (let method of methods) {
let [
min_10K_elements,
max_10K_elements
] = await runTests(method, Arr10K), [
min_10M_elements,
max_10M_elements
] = await runTests(method, Arr10M, 3),
result = {
min_10K_elements,
max_10K_elements,
min_10M_elements,
max_10M_elements
};
results[method] = result;
console.log({
method,
...result
});
}
console.table(results);
return;
})();
If you open the devtools in your browser, to see the results in a table, you'll notice for is consistently the fastest where as reduce and forEach are +- equal. The difference is negligible when testing arrays of 10K elements (and might be influenced by concurrent processes in the browser or even in your machine).
Testing an array of 10M elements, the performance of for is between 20x and 30x in comparison to reduce and forEach.
Clean code beats early overoptimization, but if your homework scores raw performance, you have now a real benchmark.
https://jsfiddle.net/JungEun1997/nb3o1987/50/
I have reached the desired result but you want to see it in a simpler way.
I tried using map and filter but failed.
I want to change this obj_wrap to obj_a in a simpler way!
(start_num and end_num differ by 1)
var obj_wrap = {
'time':[{
'start_num': 10,
'end_num':11
},{
'start_num': 3,
'end_num':4
},{
'start_num': 1,
'end_num':2
},{
'start_num': 2,
'end_num':3
},{
'start_num': 6,
'end_num':7
}]
}
var obj_a = {
'time':[{
'start_num': 1,
'end_num':4
},{
'start_num': 6,
'end_num':7
},{
'start_num': 10,
'end_num':11
}]
}
I used this method.
var obj_b = {'time':[]}
$.each(obj_wrap.time,function(time_key,time_val){
$.each(obj_wrap.time,function(chk_key,chk_val){
if(time_val.start_num === chk_val.end_num){
obj_wrap.time[time_key]['start_num'] = chk_val.start_num
obj_wrap.time[chk_key] = ""
}
if(time_val.end_num === chk_val.start_num){
obj_wrap.time[time_key]['end_num'] = chk_val.end_num
obj_wrap.time[chk_key] = ""
}
});
})
$.each(obj_wrap.time,function(key,value){
if(value!==""){
obj_b.time.push(value)
}
})
obj_b.time.sort(function (a, b) {
return a.start_num < b.start_num ? -1 : a.start_num > b.start_num ? 1 : 0;
});
You can use Bucket Sort algorithm in this case:
var obj_wrap = {
'time':[{
'start_num': 10,
'end_num':11
},{
'start_num': 3,
'end_num':4
},{
'start_num': 1,
'end_num':2
},{
'start_num': 2,
'end_num':3
},{
'start_num': 6,
'end_num':7
}]
};
var time = obj_wrap.time;
var bucket = [];
time.forEach(({start_num, end_num}) => {
for (var i = start_num; i < end_num; i++) {
bucket[i] = true;
}
});
var newTime = [];
bucket.forEach((_, index) => {
if (bucket[index - 1]) {
newTime[newTime.length - 1].end_num = index + 1;
} else {
newTime.push({start_num: index, end_num: index + 1});
}
});
var obj_a = {time: newTime};
console.log(obj_a);
The complexity is O(n).
I've implemented just a simple memoized cache of your data with the Key Value pair representing start_num & end_num values (See code comments for visual).
Once the memo has been created, you can iterate across the memo in linear time, and populate a results array accordingly. For that part, i opted for reduce, since it persists a transient state that's accessible for each iteration.
On each iteration, i basically just check to see if I should continue iterating without populating the times array. Once i've detected a break in the number chain, there's some edge case checks conducted before populating the times array with the expected results.
Time & Space Complexity is O(n).
const objWrap = {
time:[{
start_num: 10,
end_num:11
}, {
start_num: 3,
end_num:4
}, {
start_num: 1,
end_num:2
}, {
start_num: 2,
end_num:3
}, {
start_num: 6,
end_num:7
}],
};
const memo = objWrap.time.reduce((acc, next) => {
if (!Reflect.has(acc, next.start_num)) {
acc[next.start_num] = next.end_num;
}
return acc;
}, {});
/*
memo is now:
{
1: 2,
2: 3,
3: 4,
6: 7,
10: 11
}
NOTE: If you store key's as numbers in a JS object, they'll be automatically sorted.
*/
const entries = Object.entries(memo);
const result = entries
.slice(1) // iterate across all entries except the first since we'll use the first entry to initialize our accumulator.
.reduce((acc, [start,end], i, arr) => {
if (Reflect.has(memo, acc.next)) { // if we found a sequence, then just continue iterating.
acc.next = end;
} else {
acc.times.push({ // if the sequence is broken, then we have a result.
start_num: Number(acc.start), // cast back to number, as it's currently a string
end_num: acc.next,
});
if (i === arr.length - 1) { // if we've reached the end of the array, then prepare the last result as well.
acc.times.push({
start_num: Number(start),
start_end: end,
});
delete acc.next;
delete acc.start;
} else { // if we haven't reached the end of the array, then prepare the next iteration's comparison.
acc.start = start;
acc.next = end;
}
}
return acc;
}, {
next: entries[0][1], // initialize accumulator with first entryies end value.
start: entries[0][0], // initialize accumulator with first entryies start value.
times: [],
});
console.log(JSON.stringify(result, null, 2))
i have a Array,like:
{
"10-08": [
{
"Items": [
{
"RoomNum": 2
}
],
"Dates": {
"From": "2019-10-03T16:00:00.000Z",
"To": "2019-10-08T16:00:00.000Z"
}
}
],
"10-09":[
{
"Items": [
{
"RoomNum": 3
}
],
"Dates": {
"From": "2019-10-07T16:00:00.000Z",
"To": "2019-10-11T16:00:00.000Z"
}
}
],
the differenceInDays is from date-fns.js
now, i want get
(items.RoomNum * differenceInDays(item.TravelDates.To,item.TravelDates.From))
+(items.RoomNum * differenceInDays(item.TravelDates.To,item.TravelDates.From))...
and so on.
For example:
i want get:
2*5 +3*4
how can i do?
This is a great opportunity to use the reduce feature that is a function of Javascript arrays. This function reduces an array down to 1 value.
The syntax looks like this:
const array = [1, 2, 3, 4, 5];
const sum = array.reduce(function(sumSoFar, currentElement) {
return sumSoFar + currentElement;
}, 0 /* initial value of sumSoFar */);
console.log(sum); // 15
So, in your case since you've grouped items together already, the code is a bit more involved, but still not difficult. The final price could be calculated like this:
Object.keys(groups).reduce(function(sum, group) {
return sum + differenceInDays(groups[group][0].Dates.To, groups[group][0].Dates.From) * groups[group][0].Items.reduce(function(subSum, item) {
return subSum + item.RoomNum;
}, 0);
}, 0);
This works because of the distributive property of multiplication that states a * (b + c) = a * b + a * c - we can sum the number of rooms and multiply that by the number of days, and it both is equivalent to the formula you posted and yields cleaner/shorter code.
i think i need this code:
private buildNightNum(
groups: Dictionary<Model[]>,
item: string
) {
let differenceFromTo = groups[item]
.filter(t => t.Dates)
.reduce(
(a, b) => a + differenceInDays(b.Dates.To, b.Dates.From),
0
);
let roomNum = groups[item]
.filter(t => t.Items.filter(s => s.RoomNum))
.reduce(
(a, b) =>
a +
b.Items.filter(s => s.RoomNum)
.map(s => s.RoomNum)
.reduce((c, d) => c + d, 0),
0
);
return differenceFromTo* roomNum ;
}
I am trying to Sum of the key ‘total’ from the following object, but unable to find the way. I have tried to find it by using Object.key
const data = {
"item1": {},
"item2": {
"total": 13,
},
"item3": {},
"item4": {
"total": 12,
}
}
const count = Object.keys(data).map(item => data[item].total);
console.log(count);
This is what I have tried and in consol.log it is printing 13 and 12 but I am not able to do Sum of them. Also, I have tried the reduce method which is suggested in some of the following answers.
Use Object.keys() to loop over the keys of the object and then access the total property of each object:
var data = {
"item1": {
"total": 17
},
"item2": {
"total": 13
},
"item3": {}
};
var sum = 0;
Object.keys(data).forEach(key => sum += data[key].total || 0);
console.log(sum);
You can use Object.values()
The Object.values() method returns an array of a given object's own enumerable property values, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
and Array.prototype.reduce()
The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.
const data = {
"item1": {},
"item2": {
"total": 13,
},
"item3": {},
"item4": {
"total": 12,
}
}
var sum = Object.values(data)
.filter(value => Object.keys(value).length !== 0)
.reduce((a,c) => a+c.total, 0);
console.log(sum);
Use Object.values to get all the values in your data.
Then use Array.reduce to calculate the total.
const data = {
"item1": { "total": 17 },
"item2": { "total": 13 }
}
const values = Object.values(data);
console.log("Values:", values);
const total = values.reduce((a, c) => a + c.total, 0);
console.log("Total:", total);
Of course, you don't need the intermediate variable:
const total = Object.values(data).reduce((a, c) => a + c.total, 0);
const sum = Object.keys(yourObject).map(key => yourObject[key].total).reduce((a, b) => a + b, 0);