[
{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
},
{
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}]
I have many of this objects and need to take Customer and sum (add) all of his "Hs" value. So the final array would be like:
[
{
"Customer" : "Infranet",
"Total_hs" : "18"
},
{
"Customer" : "Huxley",
"Total_hs" : "11"
}
]
I tried to find out with lodash and node foreach functions but can't, could you help me please? Thanks!
First, you must make sure you have the input data as a javascript object (so if it is a json string, it will need to be parsed with something like var items = JSON.parse(input_string))
var items = [{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
}, {
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}]
... next, create array of summed Hs values...
var totals = _.reduce(items, function(memo, item) {
// make sure that the customer is created on the output object, or initialise it to zero
memo[item.Customer] = memo[item.Customer] || 0;
// increment the Hs value with the current item's Hs value
memo[item.Customer] += item.Hs;
// return the current object for the next iteration of the loop
return memo;
// pass empty object to initialise reduce
}, {});
totals should now have array of objects, with customer name as key, and total Hs as value.
... next, reformat array to match desired data format...
var target_array = _.map(totals, function(item, key) {
return {
Customer: key,
Total_hs: item
}
});
... check the out put is correct...
console.log(target_array);
Given the JSON is provided as a JavaScript object (items in the sample below):
var items = [{
"Hs": 5,
"Type": "Support",
"By": "William Shake the Speare",
"Product": "SA",
"Customer": "Huxley",
"State": "In progress"
}, {
"Hs": 2,
"Type": "Support",
"By": "Orwells",
"Product": "Web",
"Customer": "Infranet",
"State": "Closed"
}];
var collected = _.map(_.keys(_.grouped(items, "Customer")), function(k) {
return {
Customer: k,
Hs: _.reduce(grouped[k], function(accumulator, v) {
return accumulator + v.Hs;
}, 0)
};
});
Related
i have a payload
{
"category": "Mobile",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
}
i want to find all object which have rating 1 or 2 or 3 and also have any location
Basically i am creating a filter for an ecommerce store i which we will get multiple location and multiple ratings as well so we will return only those object which have matched property. i am attaching a screenshot of UI for better understanding.
i want to run this filter with multiple location and multiple checked checkbox
You can do create a filter dynamically:
const { category, price, location, rating } = req.body;
const filter = {};
if (category) filter.category = category;
if (price) filter.price = { $gte: parseInt(price.from, 10), $lte: parseInt(price.to, 10) };
if (location?.length) filter.location = { $in: location };
if (rating?.length) filter.rating = { $in: rating };
const data = await Collection.find(filter);
If you want to filter your objects, you should use filter() from your array :
const arr = [{
"category": "Mobile1",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
},
{
"category": "Mobile2",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"2",
"3"
]
}];
const result = arr.filter(el => el.rating.includes("1") || el.rating.includes("2") || el.rating.includes("3"));
console.log(result);
I'm trying to make a function in javascript in order to match a key and an array of objects from an API. The matching is based on 2 parameters coming from an API.
A key which is a string and an array of objects with keys and values.
The output of this match should be a new array of objects with the values where that passed key is matching with the key of that array of objects passed as a parameter.
I prepared a sample of what I'm trying to achieve but is not working as I don't know how to do it properly and below it will be moe details about it
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
const question = {
key: "medicines"
}
// *Matching and extracting the right criteria data for the provided question key
// *inside the criteria object
// *returns an object with the right criteria
// *doing it for every group set of rules
function questionCriteriaKeyMatch(criteriaJson, question) {
criteriaJson.map((criteria) => {
return Object.keys(criteria)
.filter((key) => {
return key === question.key;
})
.reduce((cur, key) => {
return Object.assign(cur, {
criteria: criteria[key],
});
}, {});
});
}
console.log(questionCriteriaKeyMatch(criteriaJson, question));
To explain what data we are getting that criteriaJson
This data is an array of objects which contains a set of rules divided into objects for the same item but referring to a different group.
object 1 is criteria 1 and object 2 is criteria 2 to make it simple in this specific case.
[{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
However, the cases for this data are 3 essentially
the object is empty as no criteria exist in this case from API the match with the key which doesn't exist will output null
the array has one object only so the match needs to be done on this only object and if the key does not match output null
we have an array of more than one object in this case we need to match for every single object the key and if not match output is null.
Starting with the simple case when we receive an empty array of objects
const obj = [];
const key = 'someKey';
// Output as there is no matching
[null]
Example of the second case, when we have one object in the array
const obj = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
}]
// Output matching key === age -> I'm open to suggestions how this output should be for // one obj only in the array
[{
criteria: { min:"18", max:"65" }
}]
// key === pain
[{
criteria: "5"
}]
// key === disease
[{
criteria: {valid: ["MDD","PTSD"], invalid: ["None"] }
}]
// key === notExistingKey means the key we are passing to match doesn't have a match so // we output null in this case
[{ null }]
From the above example, we output the matching values with the key passed as a param, when no match then is null
The last case is the more complex probably when we have an array of objects of the criteria and this should work for an array length > 1.
Using same data as in the snippet showing what is the expected output
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
const key = 'medicines'
// the output should be a new array of objects as we need to compare each object to find // the key match and output every single value
// key === medicines
[
{ criteria: 'true' }, -> we have a match in the first obj
{ criteria: null }, -> we have no match in the second obj
]
// key === age
[
{ criteria: { min: "18", max: "65" }}, -> we have a match in the first obj
{ criteria: { min: "16", max: "18" }}}, -> we have a match in the second obj
]
// For the rest of the keys should follow the same logic and with more objects, we have more
// objects in the output we have
I'm adding criteria as I need that in a second phase to be able to access that obj and extract the values for further use. As the keys are not the same always as are strings from API set in a client I need a way to facilitate access to the new object by assigning a hard-coded key. That is why when there is a match I just need the values and key like criteria, so I can access without an issue the values
I started with a reduce method as I thought maybe that was the way but in the end, I'm open to new solutions as cannot figure out how to achieve my goal.
The important note is that I cannot use for loops as I have strict rules of code style which cannot change.
If will be any comment with particular questions or request will try to explain better or update my question with more relevant info.
Seems like you just want to map the array to a new array with just the values. If the key does not exist, you would just set the criteria value to null, otherwise you set the criteria to whatever the property's value is.
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
function getCriteria (key, data) {
if (!data?.length) return [null]
return data.map(item => ({ criteria: item[key] || null }));
}
console.log('age', getCriteria('age', criteriaJson));
console.log('medicines', getCriteria('medicines', criteriaJson));
console.log('pressure', getCriteria('pressure', criteriaJson));
I am working on an angular application. I have an array as follows:
[{
"Name": "Andy"
},
{
"Name": "Bayer"
},
{
"Name": "James"
},
{
"Name": "Doda"
}]
I have another array which containes data as follows:
[
{
"Name": "Andy",
"Id": "1",
"Time": "2020-06-19T11:02+00:00"
},
{
"Name": "Billy",
"Id": "2",
"Time": "2020-06-19T11:05+00:00"
},
{
"Name": "Ciena",
"Id": 5
"Time": "2020-06-19T11:05+00:00"
},
{
"Name": "Doda",
"Id": "4",
"Time": "2020-06-19T11:05+00:00"
}
]
I want a resultant array such that code should check if Name is present in first array, then it should copy data from second array for that Name and push it in resultant array. For example common name between above two array is Andy and Doda, so data from Andy and Doda should be pushed to resultant array as follows:
[{
"Name": "Andy",
"Id": "1",
"Time": "2020-06-19T11:02+00:00"
},
{
"Name": "Bayer"
},
{
"Name": "James"
},
{
"Name": "Doda",
"Id": "4",
"Time": "2020-06-19T11:05+00:00"
}]
At run time I may get many names so code should be generic. I was trying following code which I got over stackoverflow itself
this.newArray = _.map(this.resultantArray, item => {
const value = _.find(this.dataArray, ['Name', item]);
const obj = value ? value : {Name: item};
return obj;
});
But this code is not working as expected as it works fine for the first time but when data comes for second time it appends data to previous data. I want array to be populated again freshly every time I send data. Please help
You can do this with vanilla JS no need for lodash. You can first map it and inside that you can find the value from second array otherwise return the current object:
var arrayTwo = [ { "Name": "Andy", "Id": "1", "Time": "2020-06-19T11:02+00:00" }, { "Name": "Billy", "Id": "2", "Time": "2020-06-19T11:05+00:00" }, { "Name": "Ciena", "Id": "5", "Time": "2020-06-19T11:05+00:00" }, { "Name": "Doda", "Id": "4", "Time": "2020-06-19T11:05+00:00" } ];
var arrayOne = [{ "Name": "Andy"}, { "Name": "Bayer"}, { "Name": "James"}, { "Name": "Doda"}];
var result = arrayOne.map(val=>arrayTwo.find(p=>p.Name==val.Name) || val);
console.log(result);
Suppose first array name is First
First : any [] = [{"Name": "Andy"},{"Name": "Bayer"},{ "Name": "James"},{"Name": "Doda"}]
And Second array name is Second
Second : any[] = [{"Name": "Andy","Id": "1","Time": "2020-06-19T11:02+00:00"},{"Name": "Bayer"},{"Name": "James"},{"Name": "Doda","Id": "4","Time": "2020-06-19T11:05+00:00"}]
Now do looping and check each name of first if its exists in second copy from second and push in result array
result : any[] =[];
this.First.forEach((element) => {
let index = this.Second.findIndex((x) => element.Name== x.Name);
if (index > -1) {
let data = {
this.Second[index].Name,
this.Second[index].Id,
this.Second[index].time,
};
this.result.push(data);
}
}
I have json as below. what i am trying to do is calculate sum of price per each user
in this case for example, user001: 91.68
where I am in stuck is I am trying to write for loop to get those data from json but I have to assign direct usernumber(e.g. user001) to code.
I want to use that like shoppingJson[i][j] something like that
I only can get result when I write below
console.log(shoppingJson[0].user001[0].price)
how should I do to access 2d array values?
var shoppingJson = [{
"user001": [
{
"productId": "123",
"name": "Product 123",
"price": 14.23
},
{
"productId": "456",
"name": "Product 456",
"price": 4.56
},
{
"productId": "789",
"name": "Product 789",
"price": 72.89
}
]},{
"user002": [
{
"productId": "321",
"name": "Product 321",
"price": 3.21
},
{
"productId": "654",
"name": "Product 654",
"price": 61.54
},
{
"productId": "987",
"name": "Product 987",
"price": 59.87
}
]},{
"user003": [
{
"productId": "777",
"name": "Product 888",
"price": 4.213
},
{
"productId": "888",
"name": "Product 999",
"price": 6.24
},
{
"productId": "999",
"name": "Product 111",
"price": 9.71
}
]}
]
shoppingJson.forEach(function(obj) {
var totalPrice = 0;
for(key in obj) {
obj[key].forEach(function(o) {
totalPrice += o.price;
});
};
console.log(totalPrice);
});
You could use a forEach loop to iterate through each of the objects within the shoppingJson array. Then you can create a variable to store the total price, and it will be initialized to zero. For each key within the object you can do another forEach iteration (because the value of that key with be the array of objects), and add the value of "price" from that object to the totalPrice variable. If you try this on the first object in the shoppingJson array you get 91.68.
var price = {};
for(item of shoppingJson){
for( user in item ){
price[user] = 0;
for(product of item[user]){
price[user] += product.price;
}
}
}
After executing this, you will get the sums in the object price. The object price will then contain the following
{
user001: 91.68,
user002: 124.62,
user003: 20.163
}
I'm pretty new to Javascript, and I just learned about underscore.js. I have a deeply nested JSON object, and I need to use underscore to find key/value pairs, which I will then use to populate various HTML tables. If the structure was more shallow, using something like _.pluck would be easy, but I just don't know how to traverse past the first couple of nesting levels (i.e. surveyGDB, table, tablenames). The JSON object comes from an XML that is comprised of multiple nesting structures (mashed up from different database tables).
var JSONData =
"surveyGDB": {
"filename": "..\\Topo\\SurveyGeoDatabase.gdb",
"table": {
"tablename": [
{
"#text": "SurveyInfo\n ",
"record": {
"OBJECTID": "1",
"SiteID": "CBW05583-345970",
"Watershed": "John Day",
"VisitType": "Initial visit",
"SurveyInstrument": "Total Station",
"ImportDate": "2015-07-22T09:08:42",
"StreamName": "Duncan Creek",
"InstrumentModel": "TopCon Magnet v2.5.1",
"FieldSeason": "2015"
}
},
{
"#text": "QaQcPoints\n ",
"record": [
{
"OBJECTID": "1",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "tp",
"Count": "357"
},
{
"OBJECTID": "2",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "tb",
"Count": "92"
},
{
"OBJECTID": "3",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "to",
"Count": "8"
},
{
"OBJECTID": "4",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "bl",
"Count": "279"
},
{
"OBJECTID": "5",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "bf",
"Count": "18"
}
]
},
{
"#text": "QaQcPolygons\n ",
"record": [
{
"OBJECTID": "1",
"TIMESTAMP": "2015-07-22T09:43:08",
"SurveyExtentCount": "",
"WaterExtentCount": "",
"ChannelUnitsCount": "",
"ChannelUnitsUnique": ""
},
{
"OBJECTID": "2",
"TIMESTAMP": "2015-07-22T13:35:15",
"SurveyExtentCount": "1",
"WaterExtentCount": "1",
"ChannelUnitsCount": "21",
"ChannelUnitsUnique": "21"
}
]
}
]
}
}
}
For instance, I wanted all of the values for 'Code' in the 'QaQCPoints' table, so I tried:
var codes = _.flatten(_.pluck(JSONData.surveyGDB.table.tablename[1].record[0], "Code" ));
console.log(codes);
In the console, this returns an array with a length of 5, but with blank values.
What am I doing wrong?
I'd also rather search for the 'Code' values in the table based on something like the '#text' key value, instead of just using it's position in the object.
If I understood you correctly, you want to always search the record array within JSONData.surveyGDB.table.tablename array for some queries. This means you need to find the record based on some parameter and return something from the found record.
Do note that the record property is sometimes an array and sometimes an object (for table SurveyInfo) in your example so I'll assume you need to take this into account.
You can make a small function to extract data and handle both objects and arrays:
function extract(record, prop) {
if (Array.isArray(record)) {
return _.pluck(record, prop);
} else {
return record[prop];
}
}
Usage example:
I wanted all of the values for 'Code' in the 'QaQCPoints' table.
I'd also rather search for the 'Code' values in the table based on something like the '#text' key value, instead of just using it's position in the object.
To achieve this you first find a record using _.find, and then extract Code values from it using the method above:
var table = JSONData.surveyGDB.table.tablename;
// find an item that has `#text` property equal to `QaQcPoints`
var item = _.find(table, function(r) {
return r['#text'] === 'QaQcPoints';
});
// extract codes from the found item's record property
var code = extract(item.record, 'Code');
// output ["tp", "tb", "to", "bl", "bf"]
Running sample:
var JSONData = {
"surveyGDB": {
"filename": "..\\Topo\\SurveyGeoDatabase.gdb",
"table": {
"tablename": [{
"#text": "SurveyInfo",
"record": {
"OBJECTID": "1",
"SiteID": "CBW05583-345970",
"Watershed": "John Day",
"VisitType": "Initial visit",
"SurveyInstrument": "Total Station",
"ImportDate": "2015-07-22T09:08:42",
"StreamName": "Duncan Creek",
"InstrumentModel": "TopCon Magnet v2.5.1",
"FieldSeason": "2015"
}
}, {
"#text": "QaQcPoints",
"record": [{
"OBJECTID": "1",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "tp",
"Count": "357"
}, {
"OBJECTID": "2",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "tb",
"Count": "92"
}, {
"OBJECTID": "3",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "to",
"Count": "8"
}, {
"OBJECTID": "4",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "bl",
"Count": "279"
}, {
"OBJECTID": "5",
"TIMESTAMP": "2015-07-22T09:18:43",
"Code": "bf",
"Count": "18"
}]
}, {
"#text": "QaQcPolygons",
"record": [{
"OBJECTID": "1",
"TIMESTAMP": "2015-07-22T09:43:08",
"SurveyExtentCount": "",
"WaterExtentCount": "",
"ChannelUnitsCount": "",
"ChannelUnitsUnique": ""
}, {
"OBJECTID": "2",
"TIMESTAMP": "2015-07-22T13:35:15",
"SurveyExtentCount": "1",
"WaterExtentCount": "1",
"ChannelUnitsCount": "21",
"ChannelUnitsUnique": "21"
}]
}]
}
}
}
function extract(record, prop) {
if (Array.isArray(record)) {
return _.pluck(record, prop);
} else {
return record[prop];
}
}
var table = JSONData.surveyGDB.table.tablename;
var item = _.find(table, function(r) {
return r['#text'] === 'QaQcPoints';
});
console.dir(item);
var code = extract(item.record, 'Code');
console.log(code);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
You have a two stage problem. Stage one is figuring out which table is QaQcPoints. If that's always JSONData.surveyGDB.table.tablename[1], you're good.
The next stage is getting your data out. You can use native array manipulation most of the time (unless you're on really old browsers). So:
var table = JSONData.surveyGDB.table.tablename[1].record;
var codeArray = table.map(function(val) { return val.Code; });
Will do the trick.