Better way to sum a property value in an array - javascript

I have something like this:
$scope.traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
Now to have a total Amount of this array I'm doing something like this:
$scope.totalAmount = function(){
var total = 0;
for (var i = 0; i < $scope.traveler.length; i++) {
total = total + $scope.traveler[i].Amount;
}
return total;
}
It's easy when is only one array, but I have others arrays with a different property name that I would like to sum.
I would be happier If I could do something like this:
$scope.traveler.Sum({ Amount });
But I don't know how to go through this in a way that I could reuse it in the future like this:
$scope.someArray.Sum({ someProperty });

I know that this question has an accepted answer but I thought I'd chip in with an alternative which uses array.reduce, seeing that summing an array is the canonical example for reduce:
$scope.sum = function(items, prop){
return items.reduce( function(a, b){
return a + b[prop];
}, 0);
};
$scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');
Fiddle

Just another take, this is what native JavaScript functions Map and Reduce were built for (Map and Reduce are powerhouses in many languages).
var traveler = [{description: 'Senior', Amount: 50},
{description: 'Senior', Amount: 50},
{description: 'Adult', Amount: 75},
{description: 'Child', Amount: 35},
{description: 'Infant', Amount: 25}];
function amount(item){
return item.Amount;
}
function sum(prev, next){
return prev + next;
}
traveler.map(amount).reduce(sum);
// => 235;
// or use arrow functions
traveler.map(item => item.Amount).reduce((prev, next) => prev + next);
Note: by making separate smaller functions we get the ability to use them again.
// Example of reuse.
// Get only Amounts greater than 0;
// Also, while using Javascript, stick with camelCase.
// If you do decide to go against the standards,
// then maintain your decision with all keys as in...
// { description: 'Senior', Amount: 50 }
// would be
// { Description: 'Senior', Amount: 50 };
var travelers = [{description: 'Senior', amount: 50},
{description: 'Senior', amount: 50},
{description: 'Adult', amount: 75},
{description: 'Child', amount: 35},
{description: 'Infant', amount: 0 }];
// Directly above Travelers array I changed "Amount" to "amount" to match standards.
function amount(item){
return item.amount;
}
travelers.filter(amount);
// => [{description: 'Senior', amount: 50},
// {description: 'Senior', amount: 50},
// {description: 'Adult', amount: 75},
// {description: 'Child', amount: 35}];
// Does not include "Infant" as 0 is falsey.

Updated Answer
Due to all the downsides of adding a function to the Array prototype, I am updating this answer to provide an alternative that keeps the syntax similar to the syntax originally requested in the question.
class TravellerCollection extends Array {
sum(key) {
return this.reduce((a, b) => a + (b[key] || 0), 0);
}
}
const traveler = new TravellerCollection(...[
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
]);
console.log(traveler.sum('Amount')); //~> 235
Original Answer
Since it is an array you could add a function to the Array prototype.
traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
Array.prototype.sum = function (prop) {
var total = 0
for ( var i = 0, _len = this.length; i < _len; i++ ) {
total += this[i][prop]
}
return total
}
console.log(traveler.sum("Amount"))
The Fiddle: http://jsfiddle.net/9BAmj/

Use reduce with destructuring to sum Amount:
const traveler = [
{ description: 'Senior', Amount: 50 },
{ description: 'Senior', Amount: 50 },
{ description: 'Adult', Amount: 75 },
{ description: 'Child', Amount: 35 },
{ description: 'Infant', Amount: 25 },
];
console.log(traveler.reduce((n, {Amount}) => n + Amount, 0));

I always avoid changing prototype method and adding library so this is my solution:
Using reduce Array prototype method is sufficient
// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);

Alternative for improved readability and using Map and Reduce:
const traveler = [
{ description: 'Senior', amount: 50 },
{ description: 'Senior', amount: 50 },
{ description: 'Adult', amount: 75 },
{ description: 'Child', amount: 35 },
{ description: 'Infant', amount: 25 },
];
const sum = traveler
.map(item => item.amount)
.reduce((prev, curr) => prev + curr, 0);
Re-useable function:
const calculateSum = (obj, field) => obj
.map(items => items.attributes[field])
.reduce((prev, curr) => prev + curr, 0);

It's working for me in TypeScript and JavaScript:
let lst = [
{ description:'Senior', price: 10},
{ description:'Adult', price: 20},
{ description:'Child', price: 30}
];
let sum = lst.map(o => o.price).reduce((a, c) => { return a + c });
console.log(sum);
I hope is useful.

I thought I'd drop my two cents on this: this is one of those operations that should always be purely functional, not relying on any external variables. A few already gave a good answer, using reduce is the way to go here.
Since most of us can already afford to use ES2015 syntax, here's my proposition:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
We're making it an immutable function while we're at it. What reduce is doing here is simply this:
Start with a value of 0 for the accumulator, and add the value of the current looped item to it.
Yay for functional programming and ES2015! :)

You can do the following:
$scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c);

I'm not sure this has been mentioned yet. But there is a lodash function for that. Snippet below where value is your attribute to sum is 'value'.
_.sumBy(objects, 'value');
_.sumBy(objects, function(o) { return o.value; });
Both will work.

can also use Array.prototype.forEach()
let totalAmount = 0;
$scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount);
return totalAmount;

From array of objects
function getSum(array, column)
let values = array.map((item) => parseInt(item[column]) || 0)
return values.reduce((a, b) => a + b)
}
foo = [
{ a: 1, b: "" },
{ a: null, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
]
getSum(foo, a) == 3
getSum(foo, b) == 6

Here is a one-liner using ES6 arrow functions.
const sumPropertyValue = (items, prop) => items.reduce((a, b) => a + b[prop], 0);
// usage:
const cart_items = [ {quantity: 3}, {quantity: 4}, {quantity: 2} ];
const cart_total = sumPropertyValue(cart_items, 'quantity');

After going through these answers I think that actually a for (or forEach or for of with await) loop is much more readable that than reduce or even map and reduce.
Think of:
coming back to this code after 6 months or maintaining this by someone else. I think your approach of using a loop is good enough.
extending this function in the future, in case you might want to add a currency conversion or similar. Doing this in a one-liner is not a great idea.
var traveler = [
{Amount: 50, description: 'Senior'},
{Amount: 50, description: 'Senior'},
{Amount: 75, description: 'Adult'},
{Amount: 35, description: 'Child'},
{Amount: 25, description: 'Infant'}
];
var sumFromArray = (propertyName, array) => {
let sum = 0;
array.forEach(item => {
sum += item[propertyName] ?? 0;
});
return sum;
};
var sumOfTraveler = sumFromArray('Amount', traveler);
console.log(sumOfTraveler);
Using types your function definition might look like:
const sumFromArray = (propertyName: string, array: Array<{[propertyName: string]: number}>) => { ... };
See here for more details: TypeScript A computed property name in a type literal must directly refer to a built-in symbol
I have nothing against map, reduce or one-liners, this is just food for thought.

You can use Array.prototype.reduce:
const sum = traveler.reduce((acc , val)=>{
return acc + val.amount;
} ,0);

How to sum array of object using Javascript
const traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 }
];
const traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
function sum(arrayData, key){
return arrayData.reduce((a,b) => {
return {Amount : a.Amount + b.Amount}
})
}
console.log(sum(traveler))
`

Here's a solution I find more flexible:
function sumOfArrayWithParameter (array, parameter) {
let sum = null;
if (array && array.length > 0 && typeof parameter === 'string') {
sum = 0;
for (let e of array) if (e && e.hasOwnProperty(parameter)) sum += e[parameter];
}
return sum;
}
To get the sum, simply use it like that:
let sum = sumOfArrayWithParameter(someArray, 'someProperty');

I was already using jquery. But I think its intuitive enough to just have:
var total_amount = 0;
$.each(traveler, function( i, v ) { total_amount += v.Amount ; });
This is basically just a short-hand version of #akhouri's answer.

You can use jscollection library for database like query job easily in just one line
https://github.com/somnathpanja/jscollection
var total = List.extend(traveler).select('Amount').sum();

i honestly got frustrated while reading all the code that where posted as a solution to this cus i'm a new be and i'n trying to add a functionality to a simple app for practice. The simple way to solve this is
let testArray = [5, 7, 8, 4];
function(){
sum = 0;
for(let i = 0; i < testArray.length; i++){
sum += testArray[i];
}
// will give you the sum of the array

Related

Summing object values per each key and converting the result into a map [duplicate]

I have something like this:
$scope.traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
Now to have a total Amount of this array I'm doing something like this:
$scope.totalAmount = function(){
var total = 0;
for (var i = 0; i < $scope.traveler.length; i++) {
total = total + $scope.traveler[i].Amount;
}
return total;
}
It's easy when is only one array, but I have others arrays with a different property name that I would like to sum.
I would be happier If I could do something like this:
$scope.traveler.Sum({ Amount });
But I don't know how to go through this in a way that I could reuse it in the future like this:
$scope.someArray.Sum({ someProperty });
I know that this question has an accepted answer but I thought I'd chip in with an alternative which uses array.reduce, seeing that summing an array is the canonical example for reduce:
$scope.sum = function(items, prop){
return items.reduce( function(a, b){
return a + b[prop];
}, 0);
};
$scope.travelerTotal = $scope.sum($scope.traveler, 'Amount');
Fiddle
Just another take, this is what native JavaScript functions Map and Reduce were built for (Map and Reduce are powerhouses in many languages).
var traveler = [{description: 'Senior', Amount: 50},
{description: 'Senior', Amount: 50},
{description: 'Adult', Amount: 75},
{description: 'Child', Amount: 35},
{description: 'Infant', Amount: 25}];
function amount(item){
return item.Amount;
}
function sum(prev, next){
return prev + next;
}
traveler.map(amount).reduce(sum);
// => 235;
// or use arrow functions
traveler.map(item => item.Amount).reduce((prev, next) => prev + next);
Note: by making separate smaller functions we get the ability to use them again.
// Example of reuse.
// Get only Amounts greater than 0;
// Also, while using Javascript, stick with camelCase.
// If you do decide to go against the standards,
// then maintain your decision with all keys as in...
// { description: 'Senior', Amount: 50 }
// would be
// { Description: 'Senior', Amount: 50 };
var travelers = [{description: 'Senior', amount: 50},
{description: 'Senior', amount: 50},
{description: 'Adult', amount: 75},
{description: 'Child', amount: 35},
{description: 'Infant', amount: 0 }];
// Directly above Travelers array I changed "Amount" to "amount" to match standards.
function amount(item){
return item.amount;
}
travelers.filter(amount);
// => [{description: 'Senior', amount: 50},
// {description: 'Senior', amount: 50},
// {description: 'Adult', amount: 75},
// {description: 'Child', amount: 35}];
// Does not include "Infant" as 0 is falsey.
Updated Answer
Due to all the downsides of adding a function to the Array prototype, I am updating this answer to provide an alternative that keeps the syntax similar to the syntax originally requested in the question.
class TravellerCollection extends Array {
sum(key) {
return this.reduce((a, b) => a + (b[key] || 0), 0);
}
}
const traveler = new TravellerCollection(...[
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
]);
console.log(traveler.sum('Amount')); //~> 235
Original Answer
Since it is an array you could add a function to the Array prototype.
traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
Array.prototype.sum = function (prop) {
var total = 0
for ( var i = 0, _len = this.length; i < _len; i++ ) {
total += this[i][prop]
}
return total
}
console.log(traveler.sum("Amount"))
The Fiddle: http://jsfiddle.net/9BAmj/
Use reduce with destructuring to sum Amount:
const traveler = [
{ description: 'Senior', Amount: 50 },
{ description: 'Senior', Amount: 50 },
{ description: 'Adult', Amount: 75 },
{ description: 'Child', Amount: 35 },
{ description: 'Infant', Amount: 25 },
];
console.log(traveler.reduce((n, {Amount}) => n + Amount, 0));
I always avoid changing prototype method and adding library so this is my solution:
Using reduce Array prototype method is sufficient
// + operator for casting to Number
items.reduce((a, b) => +a + +b.price, 0);
Alternative for improved readability and using Map and Reduce:
const traveler = [
{ description: 'Senior', amount: 50 },
{ description: 'Senior', amount: 50 },
{ description: 'Adult', amount: 75 },
{ description: 'Child', amount: 35 },
{ description: 'Infant', amount: 25 },
];
const sum = traveler
.map(item => item.amount)
.reduce((prev, curr) => prev + curr, 0);
Re-useable function:
const calculateSum = (obj, field) => obj
.map(items => items.attributes[field])
.reduce((prev, curr) => prev + curr, 0);
It's working for me in TypeScript and JavaScript:
let lst = [
{ description:'Senior', price: 10},
{ description:'Adult', price: 20},
{ description:'Child', price: 30}
];
let sum = lst.map(o => o.price).reduce((a, c) => { return a + c });
console.log(sum);
I hope is useful.
I thought I'd drop my two cents on this: this is one of those operations that should always be purely functional, not relying on any external variables. A few already gave a good answer, using reduce is the way to go here.
Since most of us can already afford to use ES2015 syntax, here's my proposition:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
We're making it an immutable function while we're at it. What reduce is doing here is simply this:
Start with a value of 0 for the accumulator, and add the value of the current looped item to it.
Yay for functional programming and ES2015! :)
You can do the following:
$scope.traveler.map(o=>o.Amount).reduce((a,c)=>a+c);
I'm not sure this has been mentioned yet. But there is a lodash function for that. Snippet below where value is your attribute to sum is 'value'.
_.sumBy(objects, 'value');
_.sumBy(objects, function(o) { return o.value; });
Both will work.
From array of objects
function getSum(array, column)
let values = array.map((item) => parseInt(item[column]) || 0)
return values.reduce((a, b) => a + b)
}
foo = [
{ a: 1, b: "" },
{ a: null, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
]
getSum(foo, a) == 3
getSum(foo, b) == 6
can also use Array.prototype.forEach()
let totalAmount = 0;
$scope.traveler.forEach( data => totalAmount = totalAmount + data.Amount);
return totalAmount;
Here is a one-liner using ES6 arrow functions.
const sumPropertyValue = (items, prop) => items.reduce((a, b) => a + b[prop], 0);
// usage:
const cart_items = [ {quantity: 3}, {quantity: 4}, {quantity: 2} ];
const cart_total = sumPropertyValue(cart_items, 'quantity');
After going through these answers I think that actually a for (or forEach or for of with await) loop is much more readable that than reduce or even map and reduce.
Think of:
coming back to this code after 6 months or maintaining this by someone else. I think your approach of using a loop is good enough.
extending this function in the future, in case you might want to add a currency conversion or similar. Doing this in a one-liner is not a great idea.
var traveler = [
{Amount: 50, description: 'Senior'},
{Amount: 50, description: 'Senior'},
{Amount: 75, description: 'Adult'},
{Amount: 35, description: 'Child'},
{Amount: 25, description: 'Infant'}
];
var sumFromArray = (propertyName, array) => {
let sum = 0;
array.forEach(item => {
sum += item[propertyName] ?? 0;
});
return sum;
};
var sumOfTraveler = sumFromArray('Amount', traveler);
console.log(sumOfTraveler);
Using types your function definition might look like:
const sumFromArray = (propertyName: string, array: Array<{[propertyName: string]: number}>) => { ... };
See here for more details: TypeScript A computed property name in a type literal must directly refer to a built-in symbol
I have nothing against map, reduce or one-liners, this is just food for thought.
How to sum array of object using Javascript
const traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 }
];
const traveler = [
{ description: 'Senior', Amount: 50},
{ description: 'Senior', Amount: 50},
{ description: 'Adult', Amount: 75},
{ description: 'Child', Amount: 35},
{ description: 'Infant', Amount: 25 },
];
function sum(arrayData, key){
return arrayData.reduce((a,b) => {
return {Amount : a.Amount + b.Amount}
})
}
console.log(sum(traveler))
`
Here's a solution I find more flexible:
function sumOfArrayWithParameter (array, parameter) {
let sum = null;
if (array && array.length > 0 && typeof parameter === 'string') {
sum = 0;
for (let e of array) if (e && e.hasOwnProperty(parameter)) sum += e[parameter];
}
return sum;
}
To get the sum, simply use it like that:
let sum = sumOfArrayWithParameter(someArray, 'someProperty');
You can use Array.prototype.reduce:
const sum = traveler.reduce((acc , val)=>{
return acc + val.amount;
} ,0);
I was already using jquery. But I think its intuitive enough to just have:
var total_amount = 0;
$.each(traveler, function( i, v ) { total_amount += v.Amount ; });
This is basically just a short-hand version of #akhouri's answer.
You can use jscollection library for database like query job easily in just one line
https://github.com/somnathpanja/jscollection
var total = List.extend(traveler).select('Amount').sum();
i honestly got frustrated while reading all the code that where posted as a solution to this cus i'm a new be and i'n trying to add a functionality to a simple app for practice. The simple way to solve this is
let testArray = [5, 7, 8, 4];
function(){
sum = 0;
for(let i = 0; i < testArray.length; i++){
sum += testArray[i];
}
// will give you the sum of the array

Convert specific property form Record into Array in Typescript/Javascript

Need to convert Record Type in Typescript/Javascript to Array with specific property
const store: Record<ProductID, ProductObject> = {
'france': productObject:{
present: 'in_stock',
amount: 23,
},
'uk': productObject:{
present: 'in_stock',
amount: 20,
},
'japan': productObject:{
present: 'no_stock',
amount: 0,
},
}
Output: Creating New Array. Adding new key as 'country' & take only 'amount' property from store Record type.
const newArrayFromRecord = [
{country: 'france', amount: 23},
{country: 'uk', amount: 20}
{country: 'japan', amount: 0}
]
I have tried with Object.entries() and then pushing in Array. But all require unnecessary code. Is there any efficient way to do..
This is one possible way to achieve the objective:
Object.entries(store).map(([k, v]) => ({
country: k,
amount: v.amount
}))
Code Snippet using JS:
const store = {
'france': {
present: 'in_stock',
amount: 23,
},
'uk': {
present: 'in_stock',
amount: 20,
},
'japan': {
present: 'no_stock',
amount: 0,
},
};
console.log(
'result: ',
Object.entries(store).map(([k, v]) => ({
country: k,
amount: v.amount
}))
);
And, here's a TypeScript Playground link.
You could just loop over the store object using a for in loop.
Or mapping it with Object.keys.
Aside from that I don't think there is really a more "efficient" solution.
const store = {
france: {
present: "in_stock",
amount: 23,
},
uk: {
present: "in_stock",
amount: 20,
},
japan: {
present: "no_stock",
amount: 0,
},
};
const result = [];
for (const country in store) {
result.push({ country, amount: store[country].amount });
}
const result_2 = Object.keys(store).map((country) => ({
country,
amount: store[country].amount,
}));
console.log(result);
console.log(result_2);
Using Object.entries and destructuring
const data = {
'france': {
present: 'in_stock',
amount: 23,
},
'uk': {
present: 'in_stock',
amount: 20,
},
'japan': {
present: 'no_stock',
amount: 0,
},
};
const res = Object.entries(data).map(([country, { amount }]) => ({
country,
amount,
}));
console.log(res);

Update a element inside object in aobject array with Immutability helper js

I need to add or subtract a value of a element in object array using Immutability helper
const selectedFood= [
{id: uuidv4(), name: "pizza", price: 1700, amount: 3},
{id: uuidv4(), name: "cheese", price: 600, amount: 10},
{id: uuidv4(), name: "fried rice", price: 500, amount: 4},
{id: uuidv4(), name: "coke", price: 100, amount: 5}]
const [foodArray, setFoodArray] = useState(selectedFood);
This code works flawlessly and this is what i want except the index
setFoodArray((prev) => {
return update(prev, {2: {amount: {$apply: function(x) {return x -1}}}})
})
the number 2 here should be the index
so i used this to get the index
const index = foodArray.indexOf(foodArray.find((single) => {
return single.id === id
}));
putting this index variable there dosn't work
setFoodArray((prev) => {
return update(prev, {index: {amount: {$apply: function(x) {return x -1}}}})
})
Picture for understanding better
can anyone help
Use bracket notation:
setFoodArray((prev) => {
return update(prev, {[index]: {amount: {$apply: function(x) {return x -1}}}})
})

2 arrays with json problem (Node.js, Discord.js)

The first array is:
[
{
id: "megaphone",
name: "Megaphone",
kind: "Consumable",
description: "Unmutes you if you are currently muted",
price: 10,
},
{
id: "expcharge",
name: "Exp Charge",
kind: "Consumable",
description: "Double exp for an hour",
price: 50,
},
{
id: "commonlootbox",
name: "Common Lootbox",
kind: "Consumable",
description: "Chance for a random amount of coins or an item",
price: 1,
},
];
The second part of the JSON I need is into a JSON file.
I tried to add the data of the json like this:
arr.forEach((a) => {
no.push(shop.find((i) => i.id === a.name));
});
And this is perfect, because i get only the data i need.
But the result is that i have two arrays now.
The second is:
[
{ name: "megaphone", quantity: 5 },
{ name: "expcharge", quantity: "3" },
{ name: "commonlootbox", quantity: "3" },
];
Now, what I need to do is basically for Each object in the array, I need to do
"array1.name - array2.quantity (array1.description)"
I need to post it like
Megaphone - 5 (Unmutes you if you are currently muted)
Common Lootbox - 3 (Double exp for an hour)
etc.
Hope this is clear.
Maybe my method is wrong?
well, you need to itirate over the second array and make strings of the result that you want, like so
const secondArray = [
{name: 'megaphone', quantity: 5}
{name: 'expcharge', quantity: '3'}
{name: 'commonlootbox', quantity: '3'}
]
const desiredarray = secondArray.map(item => {
const matchedItem = data.find(({ id }) => id == item.name)
return `${matchedItem.name} - ${item.quantity} (${matchedItem.description})`
});
I think you could store one or both arrays in a Map or directly in an object.
You could try something like this:
obj = array.reduce((obj, element) => {
obj[element.id] = element;
return obj;
}, {});
Now you can iterate one of the arrays and access the corresponding value in the other one directly.
Ciao, you could do something like this:
Solution with array of JSON:
const arr1 = [{id: 'megaphone', name: 'Megaphone', kind: 'Consumable', description: 'Unmutes you if you are currently muted', price: 10},
{id: 'expcharge', name: 'Exp Charge', kind: 'Consumable', description: 'Double exp for an hour', price: 50},
{id: 'commonlootbox', name: 'Common Lootbox', kind: 'Consumable', description: 'Chance for a random amount of coins or an item', price: 1}];
const arr2 = [{name: 'megaphone', quantity: 5},
{name: 'expcharge', quantity: '3'},
{name: 'commonlootbox', quantity: '3'}];
let arr3 = arr1.map(item1 => {
let ok_el = {};
arr2.map(item2 => {
if (item1.id === item2.name) {
ok_el.id = item1.id;
ok_el.name = item1.name;
ok_el.quantity = item2.quantity;
ok_el.description = item1.description;
return ok_el;
}
});
return ok_el;
});
let result = arr3.map(el => {
return el.name + " - " + el.quantity + " (" + el.description + ")";
});
console.log(result);
Solution with JSON of JSONs:
const arr1 = {0:{id: 'megaphone', name: 'Megaphone', kind: 'Consumable', description: 'Unmutes you if you are currently muted', price: 10},
1:{id: 'expcharge', name: 'Exp Charge', kind: 'Consumable', description: 'Double exp for an hour', price: 50},
2:{id: 'commonlootbox', name: 'Common Lootbox', kind: 'Consumable', description: 'Chance for a random amount of coins or an item', price: 1}};
const arr2 = {0:{name: 'megaphone', quantity: 5},
1:{name: 'expcharge', quantity: '3'},
2:{name: 'commonlootbox', quantity: '3'}};
let arr3 = Object.values(arr1).map(item1 => {
let ok_el = {};
Object.values(arr2).map(item2 => {
if (item1.id === item2.name) {
ok_el.id = item1.id;
ok_el.name = item1.name;
ok_el.quantity = item2.quantity;
ok_el.description = item1.description;
return ok_el;
}
});
return ok_el;
});
let result = arr3.map(el => {
return el.name + " - " + el.quantity + " (" + el.description + ")";
});
console.log(result);

Loop through an object of objects and extract key value that equals something specific?

I am trying to avoid dependencies such as loaddash (_.filter) and use pure javascript.
Basically I have an object of objects, and I need to loop through and filter out all that dont have a parent_id of a specific value.
var filterBy = 50
var obj = {
256: {
name: john
parent_id: 50
},
341: {
name: dwit
parent_id: 50
},
398: {
name: ryan
parent_id: 30
},
421: {
name: jack
parent_id: 50
}
}
with the result being
var filteredOBJ = {
256: {
name: john
parent_id: 50
},
343: {
name: dwit
parent_id: 50
},
421: {
name: jack
parent_id: 50
}
}
const result = {};
for(const [key, val] of Object.entries(obj)) {
if(val.parent_id === filterBy) {
result[key] = val;
}
}
Just turn what you described into code and you're done.
If you like the loadash approach, but want to use javascript, reduce() on the Object.entries() will give you nice functional approach, although the above forEach solutions probably win for readabilty.
var filterBy = 50
var obj = {256: {name: 'john',parent_id: 50},341: {name: 'dwit',parent_id: 50},398: {name: 'ryan',parent_id: 30},421: {name: 'jack',parent_id: 50}}
let r = Object.entries(obj).reduce((a, [k, v]) =>
v.parent_id === filterBy
? Object.assign(a, {[k]: v})
: a, {})
console.log(r)
Here's an implementation of a simple filter in ES6 :
let myObj = {
256: {
name: "john",
parent_id: 50
},
341: {
name: "dwit",
parent_id: 50
},
398: {
name: "ryan",
parent_id: 30
},
421: {
name: "jack",
parent_id: 50
}
}
let result = {};
Object.entries(myObj).forEach( ([key, value]) => {
if(key != 398) // condition over keys
result[key] = value;
})
console.log(result);
There is a counterpart Object.fromEntries() to Object.entries() so you can use vanilla javascript Array.prototype.filter(). Just convert object to entries, filter and convert back from entries to object.
const filterBy = 50
const obj = {256: {name: 'john',parent_id: 50}, 341: {name: 'dwit',parent_id: 50}, 398: {name: 'ryan',parent_id: 30}, 421: {name: 'jack',parent_id: 50}}
const filteredObj = Object.fromEntries(
Object.entries(obj).filter(
([key, value]) =>
value.parent_id === filterBy
)
)
console.log(filteredObj)

Categories

Resources