Group the data in an array and get the sum from the array of object values - javascript

I am new to react and javascript. Here I am trying to use the lodsh function.
I have an array of object which looks like ,
const data = [{
"Id": "1",
"testone": 100,
"test": 40,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "INP"
}
}, {
"Id": "2",
"testone": 120,
"test": 20,
"Original": {
"Id": "10"
},
"__Parent__": {
"Id": "21",
"Status": "Book"
}
},{
"Id": "3",
"testone": 110,
"test": 140,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "INP"
}
}, {
"Id": "4",
"testone": 100,
"test": 40,
"Original": {
"Id": "11"
},
"__Parent__": {
"Id": "20",
"Status": "Val"
}
}]
Here, I have one function which has the product Id . which I am passing from another function =>
cont value = (PID, data) => {
}
So, this function ,
I need do sum , where first I need to take all the object which has the same Id as PID. The Id from object is to be Original.ID. If these matches then after that ,I need to check the status of that objects like , is status is either INP or BOOK then for summation need to take the
testone key value or else need to take the `test` key value.
So, In the given example it will be like ,
Id is 11 which is passed to a function and in the given object 3 objects where it matches.
Now,
while returning sum it will be like ,
100 + 100 + 40 which will be 240.
So, How do I do this . thanks .

I think it's best to do it with Array.reduce if you support IE9 and after.
const sum = data.reduce((total, item) => {
if (item.Original.Id !== PID) return total;
const { status, testone, test } = item;
let addition = 0;
if (status === "INP") addition = testone;
else if (status === "BOOK") addition = test;
return total + addition;
}, 0);

Related

Check if array of objects, which also contain nested arrays with objects, are the same, if so, combine them into one object and add the keys together

I would need to check if the objects in the "food" array are equal to each other, and the ones that are - combine into one adding amount and mody.amount and leaving the rest unchanged. This is just for better order data displaying. I tried with lodash library and reduce but but I don't know exactly how to construct this function that nested objects(mody) adds values ​​as well, and in case isEqual returns false keep the object while concurrently concatenating the identical ones.
What I tried:
obj1.reduce((prev, next) => _.isEqual(prev, next) ? {...prev, amount: prev.amount + next.amount} : next
Now it looks like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
and would need something like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 2,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 2
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 2
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
The algorithm to sum the food amounts and mody amounts are almost the same, the difference is that for each food that has the same id we will sum the mody amount. To make the algorithm simpler I used a dictionary as the accumulator on the reduce function so we have a unique element per key. This element will be our final food or mody with the amount sum.
Mody sum algoritm:
const sumMody = (modyAccumulator, currentMody) => {
//Get the stored mody in the accumulator dictionary or null if it the mody is not stored
const storedMody = modyAccumulator[currentMody.id] ?? null
// if mody is null then add mody to the dictionary using its id as key
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
//Mody is stored then sum amount
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
The food sum algoritm is the same as the sumMody, the only difference is that it calls the sumMody function when the foods are equal:
const sumFood = (foodAccumulator, currentFood) => {
//Get the stored foodin the accumulator dictionary or null if it the food is not stored
const storedFood = foodAccumulator[currentFood.id] ?? null
// if food is null then add food to the dictionary using its id as key
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
//Food is stored then sum food amount
storedFood.amount += currentFood.amount
//Create a list with mody from both foods
const modyList = [...storedFood.mody, ...currentFood.mody]
//Use reduce passing the sumMody callback function and initialize the accumulator with a dictionary
const modySumDictionary = modyList.reduce(sumMody, {})
/* The function above return a dictionary where the identifier is the mody.id
and the value is the mody. We only need the values from that dictionary so
we use Object.values to extract all the values. */
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
To execute both sums:
//As explained before the reduce function will return a dictionary so we use Object.values to get only the values
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Algoritm without comments:
const sumMody = (modyAccumulator, currentMody) => {
const storedMody = modyAccumulator[currentMody.id] ?? null
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
const sumFood = (foodAccumulator, currentFood) => {
const storedFood = foodAccumulator[currentFood.id] ?? null
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
storedFood.amount += currentFood.amount
const modyList = [...storedFood.mody, ...currentFood.mody]
const modySumDictionary = modyList.reduce(sumMody, {})
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Reference to Object.values

Compare two json files and add number to object if object with same value is still there

Lets say i have 2 Json responses from a server, one of which is 30 seconds older that the new one. How would i be able to check if an object is still inside the response and after testing if it is still there update an object in another json file to add +1 to the number of that object.
(an example because i can´t explain)
JSON coming in
"names and id´s in json changed"
{
"description": "Insert description here;",
"favicon": null,
"latency": 78.085,
"players": {
"max": 20,
"online": 3,
"sample": [
{
"id": "07bda75d-d8d2-4108-94a7-ba2c09127nsj",
"name": "oajhebskaa"
},
{
"id": "8d8aac43-112b-402b-8771-67b49183lazf",
"name": "jahebianl"
},
{
"id": "67d8a66b-ce37-439f-9020-e6de827dn2o9",
"name": "ffwqehas"
}
]
},
"version": {
"name": "Paper 1.16.4",
"protocol": 754
}
}
After cutting out wanted values it looks like this :
[
'07bda75d-d8d2-4108-94a7-ba2c09127nsj',
'8d8aac43-112b-402b-8771-67b49183lazf',
'67d8a66b-ce37-439f-9020-e6de827dn2o9'
]
What i want to do
Now upon a new response coming in i want to update another json file which should idealy look something like this...
{
"players" : [
{ "07bda75d-d8d2-4108-94a7-ba2c09127nsj": "0" },
{ "8d8aac43-112b-402b-8771-67b49183lazf": "0" },
{ "67d8a66b-ce37-439f-9020-e6de827dn2o9": "0" }
]
}
...and add 1 to the number behind a the certain playerid.
Something like this should work.
let samplePayload = {
"description": "Insert description here;",
"favicon": null,
"latency": 78.085,
"players": {
"max": 20,
"online": 3,
"sample": [{
"id": "07bda75d-d8d2-4108-94a7-ba2c09127nsj",
"name": "oajhebskaa"
},
{
"id": "8d8aac43-112b-402b-8771-67b49183lazf",
"name": "jahebianl"
},
{
"id": "67d8a66b-ce37-439f-9020-e6de827dn2o9",
"name": "ffwqehas"
}
]
},
"version": {
"name": "Paper 1.16.4",
"protocol": 754
}
};
let previousResponseIds = [];
let trackingObj = {};
function responseMiddleware(payload) {
let responseIds = payload.players.sample.map(v => v.id);
let matches = previousResponseIds.filter(v => responseIds.find(x => x === v));
for (let i = 0; i < matches.length; i++) {
if (trackingObj.hasOwnProperty(matches[i])) trackingObj[matches[i]] += 1;
else trackingObj[matches[i]] = 0;
}
previousResponseIds = responseIds;
}
/*UI below*/
let pre = document.getElementsByTagName('pre')[0];
(function updateUI() {
pre.innerText = JSON.stringify(trackingObj, null, 1);
setTimeout(updateUI, 200);
})();
document.getElementById("AddResponse").addEventListener("click", function() {
responseMiddleware(samplePayload);
});
<strong>trackingObj:</strong>
<pre></pre>
<button id="AddResponse">Simulate Response</button>
Let's start with
{
"players" : [
{ "07bda75d-d8d2-4108-94a7-ba2c09127nsj": "0" },
{ "8d8aac43-112b-402b-8771-67b49183lazf": "0" },
{ "67d8a66b-ce37-439f-9020-e6de827dn2o9": "0" }
]
}
let mainObj = JSON.parse(response1);
let players = JSON.parse(response2);
for (let entry of mainObj.players.sample) {
if (players.players.indexOf(entry.id) > -1) {
players.players[entry.id]++;
}
}
I don't have a chance to test it right this moment, give it a shot, and it should put you on the right track.

Find value of an object in json, node.js

I need a way to find the kills and deaths (etc.) of the corresponding name that is inputted, and if the name is not in the object I need it to output something too.
Something like this:
if (medic does not have(name)) return;
const kills = medic.(name).kills
Sample JSON:
{
"assault": {
"general": {
"kills": 1134,
"deaths": 1122,
"abc": "123"
},
"list": {
"A": {
"name": "name1",
"kills": 12,
"deaths": 120
},
"B": {
"name": "name2",
"kills": 23,
"deaths": 53
}
}
},
"support": {
"general": {
"kills": 123,
"deaths": 11232,
"abc": "11233"
},
"list": {
"A": {
"name": "name4",
"kills": 12,
"deaths": 120
},
"B": {
"name": "name5",
"kills": 23,
"deaths": 53
}
}
}
}
First clean your data to get a nice list of the names and info:
const listOfNames = [...Object.values(data.assault.list), ...Object.values(data.support.list)]
Then use the find method on that list to search for a name, with the backup of "Not Found" if the search returns undefined:
const search = (name) => listOfNames.find(item => item.name===name) || "Not Found"
Then you can use that search function elsewhere:
console.log(search("name2")) gives
See it in action here:
https://repl.it/#LukeStorry/62916291
Do you need assault and support to be sum up or all you need is one of those? Is your data always on the same shape? I'm going to assume that it is, and I'll provide both, the sum and the individual one:
const data = // your JSON here
const getAssaultKills = name => (data.assault.list[name] || {kills: 0}).kills
const getSupportKills = name => (data.support.list[name] || {kills: 0}).kills
const getTotalKills = name =>
getSupportKills(name) + getAssaultKills(name)
getTotalKills("A") // => 24
getTotalKills("C") // => 0

Get the object value based on input objects in javascript

I would like to how to get the value based on input objects in javascript.
If the source matches the currency and also matches the type in paymentin and paymentout in object then get the value of speed and fees
for example 'SGD' with type_in 'credit' and type_out 'bank' should return the speed and fee
Expected Output:
id: transfer credit: 1 days 1% pay_in: pay_out: bank
id: insta debit: 1 days 1.5% pay_in: pay_out: bank
I tried but i got stuck
function getValue(source,typein,typeout,obj){
var filterArr = source.filter(function(value){
return value.country_from.filter(function(payin){
const in= payin.paymentIn.filter(function(ty){
return ty.type == typein
})
const out = payin.paymentIn.filter(function(ty){
return ty.type == typeout
})
})
})
}
var result = getValue(source,type_in,type_out,obj);
//input objects
var source="SGD";
var type_in="credit";
var type_out="bank";
var obj = [{
"id": "transfer",
"country_from": [{
"currency": [
"SGD",
"USD"
],
"paymentIn": [{
"type": "credit",
"speed": {
"unit": "days",
"number": "1"
},
"fee": {
"type": "%",
"number": "1"
}
}],
"paymentOut": [{
"type": "bank",
"speed": {
"unit": "days",
"number": "2"
}
}]
}]
}, {
"id": "insta",
"country_from": [{
"currency": [
"SGD",
"USD"
],
"paymentIn": [{
"type": "credit",
"speed": {
"unit": "days",
"number": "1"
},
"fee": {
"type": "%",
"number": "1.5"
}
}],
"paymentOut": [{
"type": "bank",
"speed": {
"unit": "days",
"number": "2"
}
}]
}]
}]
I think you have made some mistakes on your initial code, but I guess it is due to the confusion of dealing with so many layers of objects and arrays. This is what you should do:
const getValue = (source, typein, typeout, obj) => {
const res = obj.map(item => {
if (item['country_from'][0]['paymentIn'][0]['type'] === typein
&& item['country_from'][0]['currency'].includes(source)
&& item['country_from'][0]['paymentOut'][0]['type'] === typeout) {
return `id: ${item['id']} credit: ${item['country_from'][0]['paymentIn'][0]['speed']['number']} days credit: ${item['country_from'][0]['paymentIn'][0]['fee']['number']}${item['country_from'][0]['paymentIn'][0]['fee']['type']} pay_in: pay_out: ${item['country_from'][0]['paymentOut'][0]['speed']['number']}`
}
});
return res;
}
getValue('SGD', 'credit', 'bank', obj);
Basically, I will iterate through every element of the input array, obj (which is the one you posted on your question), and within each iteration, I check for the following 3 conditions using the if statement.
1) The paymentIn type matches typein
2) The paymentOut type matches typein
3) currency contains source
Elements that fulfil the above 3 conditions will the string result.
EDIT: To answer your question on the comments, if the paymentIn array has more than one object, we can use Array.some() to check if the object with the type property has the same value as typeIn.
if (item['country_from'][0]['paymentIn'].some(payment => payment['type']===typein)
&& item['country_from'][0]['currency'].includes(source)
&& item['country_from'][0]['paymentOut'][0]['type'] === typeout) {
// to get the object with that typein
const filteredPaymentIn = item['country_from'][0]['paymentIn'].filter(payment => payment['type']===typein)[0];
}

How to check that object with same ID (or any other attribute ) exists in array of objects?

I have following array:
var array = [
{
"milestoneTemplate": {
"id": "1",
"name": "TEST1"
},
"id": "1",
"date": "1416680824",
"type": "ETA",
"note": "Note",
"color": "66FF33"
},
{
"milestoneTemplate": {
"id": "2",
"name": "Test 2"
},
"id": "2",
"date": "1416680824",
"type": "ATA",
"note": "Note 22",
"color": "66FF00"
}
];
And now i would like to check in forEach loop that object (which is passed in param of the function) is existing in array by his ID.
In case that not = do push into existing array.
arrayOfResults.forEach(function(entry) {
if(entry != existingInArrayByHisId) {
array.push(entry);
}
});
Thanks for any advice
You could create a helper function thats checks if an array contains an item with a matching property value, something like this:
function checkForMatch(array, propertyToMatch, valueToMatch){
for(var i = 0; i < array.length; i++){
if(array[i][propertyToMatch] == valueToMatch)
return true;
}
return false;
}
which you can then use like so:
arrayOfResults.forEach(function (entry) {
if (!checkForMatch(array, "id", entry.id)) {
array.push(entry);
}
});

Categories