Below is my Attempt, I have an object which has array of objects within it, it has a field: 'positionTitle'.
I also have an array of objects which also has a 'positionTitle'
They both have similar data I want all of the values for the positionTitles in my 'individualsData' to go into 'graphData' and be able to now use this new graphData!
I think my attempt is wrong its treating them both as arrays?
Thanks, Dale
graphData = {
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
},
{
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"position": {
"id": "3434",
"positionTitle": "Manager"
}
}]
}]
}
]
}]
}, {
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"position": {
"id": "4545",
"positionTitle": "Senior Manager"
}
}]
}]
}
IndividualData = [{
"account": {
"id": "001b000003WnPy1AAF",
"fullName": "Adnan A. Khan"
},
"positions": [{
"id": "a16b0000004AxeBAAS",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Senior Manager, Energy",
"positionLevel": "5-Middle Management & Advisers",
"isPrimary": true,
"startDate": "2016-10-07",
"endDate": null
}]
}, {
"account": {
"id": "0010X000048DDMsQAO",
"fullName": "Christine Leong"
},
"positions": [{
"id": "a160X000004nKfhQAE",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Managing Director",
"positionLevel": "4-Head of Business Unit/Head of Region",
"isPrimary": true,
"startDate": "2018-03-05",
"endDate": null
}]
}
What I expect to see:
NEWgraphData = {
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
},
{
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"position": {
"id": "3434",
"positionTitle": "Senior Manager, Energy" <== from individualsdata
}
}]
}]
}
]
}]
}, {
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"position": {
"id": "4545",
"positionTitle": "Managing Director" <== also from individuals data
}
}]
}]
}
graphData.engagementAreas.map((el, i) => {
el.engagementTypes.engagements.members.position.positionTitle = individualsData.positions.positionTitle;
return el;
})
As engagementTypes, engagements and members properties are also array of objects, you have to loop them as well as below.
graphData.engagementAreas.map((el, i) => {
el.engagementTypes.forEach((et) => {
et.engagements.forEach((eg) => {
eg.members.forEach((mem) => {
mem.position.positionTitle = individualsData.positions.positionTitle; // make sure this is correct
});
});
});
return el;
})
Here is the solution. but you have to choose what individual data item will be the pick for the positionTitle
graphData.engagementAreas.map((el, i) => {
return el.engagementTypes.map((el2,i2) => {
return el2.engagements.map( (el3,i3) => {
return el3.members.map((el4,i4) => {
return el4.position.positionTitle =individualsDt[0].positions.[0].positionTitle;// take a look here, i just pick positionTitle staticly
})
})
})
});
see implementation in console here enter link description here
Related
Trying to get my head around this one..
Incoming data looks like:
[
{
"value": {
"label": "MZ Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Lionel Carter"
}
},
{
"value": {
"label": "BW Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Jerome Yost"
}
},
{
"value": {
"label": "Detergent",
"type": "case",
"incident": null,
"personName": "Jerald Legros"
}
}
]
I would like to transform this into
[
{
"label": "Algal bloom",
"children": [
{ "label": "Lionel Carter", "type": "case"},
{ "label": "Jerome Yost", "type": "case" }]
},
{ "label": "Detergent", "type": "case" }
]
Basically, the rule is that if incident is not NULL then the incident name becomes the parent and the children hold the personName - otherwise we simply pass through the label and type. I can walk the array and switch out the label with the incident name, but I'm not sure how to group up the incidents..
It's basic grouping with an exception for elements without incident.
You can group the elements without incident in a separate group:
const data = [{"value": {"label": "MZ Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Lionel Carter"}},{"value": {"label": "BW Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Jerome Yost"}},{"value": {"label": "Detergent","type": "case","incident": null,"personName": "Jerald Legros"}}];
function group(data) {
const result = data.reduce((acc, { value }) => {
if (!value.incident) {
acc.ungrouped.push({ label: value.label, type: value.type });
} else {
if (!acc.groups[value.incident.name]) acc.groups[value.incident.name] = { label: value.incident.name, children: [] };
acc.groups[value.incident.name].children.push({ label: value.personName, type: value.type });
}
return acc;
}, { groups: {}, ungrouped: [] });
return [...Object.values(result.groups), ...result.ungrouped];
}
console.log(group(data));
I've been playing around trying to learn in an API project using Postman and conducting tests using JavaScript. So far, I have succeeded with the help of reading on websites and watching YouTube videos. Of course, previous tests and playing around have been fairly easy but now I came to a stop. I really tried to figure this out for several weeks but I need further guidance, a push in the right direction or direct help.
What I'm trying to do is to filter out some of the response to only view objects that contain specific data.
To do that, I'm using a filter where I want all products containing a specific value inside an array "product_option_values".
My first approach was to see if I could sort products having any values from the first array, and it worked. It filters just fine.
var filterSmall = jsonData.products.filter(fs => fs.associations.product_option_values);
My next approach was to get to my goal of filtering out products according to specific values inside this array. I tried many simple .(dot) combinations and pointing to [index] to access it without any luck. (I must add that I know how to access this from a specific product, but that way doesn't work when filtering).
I've also tried other approaches such as:
var filterSmall = jsonData.products.filter(fs => fs.associations["product_option_values", 0, "name"] === "S");
and other similar combinations.
This is a very shortened sample of the structure of "products" which in its full form consists of 20 products and far more values inside of it:
{
"products": [
{
"id": 16,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Mountain fox notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "22"
},
{
"id": "23"
}
]
}
},
{
"id": 17,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Brown bear notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "23"
},
{
"id": "24"
}
]
}
}
]
}
and here is a small and expanded sample from product_option_values:
{
"product_option_values": [
{
"id": 1,
"id_attribute_group": "1",
"color": "",
"position": "0",
"name": "S"
},
{
"id": 2,
"id_attribute_group": "1",
"color": "",
"position": "1",
"name": "M"
},
{
"id": 3,
"id_attribute_group": "1",
"color": "",
"position": "2",
"name": "L"
}
]
}
How do I proceed? Did I do anything correct or even close to it?
Perhaps I've been staring at this for too long.
Thanks in advance.
If you want to compare nested attributes you have to transform the objects (e.g. by using a map operation), so that the relevant attributes are easily accessible for a comparison. If you want to filter by product_option_value id, you could do something like this:
const jsonData = {
"products": [
{
"id": 16,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Mountain fox notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "22"
},
{
"id": "23"
}
]
}
},
{
"id": 17,
"manufacturer_name": "Graphic Corner",
"quantity": "0",
"price": "12.900000",
"indexed": "1",
"name": "Brown bear notebook",
"associations": {
"categories": [
{
"id": "2"
},
{
"id": "6"
}
],
"product_option_values": [
{
"id": "23"
},
{
"id": "24"
}
]
}
}
]
};
const sample = {
"product_option_values": [
{
"id": 22,
"id_attribute_group": "1",
"color": "",
"position": "0",
"name": "S"
},
{
"id": 2,
"id_attribute_group": "1",
"color": "",
"position": "1",
"name": "M"
},
{
"id": 3,
"id_attribute_group": "1",
"color": "",
"position": "2",
"name": "L"
}
]
};
const ids = sample.product_option_values.map((el) => String(el.id));
console.log(ids);
const filtered = jsonData.products.filter((fs) => fs.associations.product_option_values.map((e) => e.id).some((f) => ids.includes(f)));
console.log(filtered);
I have this structure below, and I want to loop through the hierarchy without missing any object.
{
"countries": [
{
"name": "Denmark",
"id": "APA1",
"children": [
{
"name": "Zealand",
"id": "APA1.1",
"parentId": "APA1",
"children": [
{
"name": "Copenhagen",
"id": "APA1.1.1",
"parentId": "APA1.1",
"children": [
{
"name": "Dublin",
"id": "ANA1",
"parentId": "APA1.1.1.1",
"hostNames": [
{
"ip": "20.190.129.1"
},
{
"ip": "20.190.129.2"
}
]
}
]
}
]
},
{
"name": "Jutland",
"id": "APA1.2",
"parentId": "APA1",
"children": [
{
"name": "Nordjylland",
"id": "APA1.2.1",
"parentId": "APA1.2",
"children": [
{
"name": "Aalborg",
"id": "APA1.2.1.1",
"parentId": "APA1.2.1",
"children": [
{
"name": "Risskov",
"id": "ANA3",
"parentId": "APA1.2.1.1",
"hostNames": [
{
"ip": "40.101.81.146"
}
]
},
{
"name": "Brabrand",
"id": "ANA4",
"parentId": "APA1.2.1.1",
"hostNames": [
{
"ip": "43.203.94.182"
}
]
}
]
}
]
}
]
}
]
}
]
}
The reason why I want to loop through the hierarchy is that I want to turn this into a flat structure. So essentially I'm gonna take every object and move it to another array which has the structure that I want. I just want to know how to access the children.
The wanted result:
"applicationGroups": [
{
"id" : "APA1",
"name": "Denmark",
},
{
"name": "Zealand",
"id": "APA1.1",
"parentId": "APA1"
},
{
"name": "Copenhagen",
"id": "APA1.1.1",
"parentId": "APA1.1"
},
{
"name": "Dublin",
"id": "ANA1",
"parentId": "APA1.1.1.1"
},
{
"name": "Jutland",
"id": "APA1.2",
"parentId": "APA1"
},
{
"name": "Nordjylland",
"id": "APA1.2.1",
"parentId": "APA1.2"
},
{
"name": "Aalborg",
"id": "APA1.2.1.1",
"parentId": "APA1.2.1"
},
{
"name": "Risskov",
"id": "ANA3",
"parentId": "APA1.2.1.1"
},
{
"name": "Brabrand",
"id": "ANA4",
"parentId": "APA1.2.1.1"
}
]
I'm a bit new to JavaScript, and I don't really know where to start, but this example that I have given is not identical to the actual one that I'm working on, so I just want the principle so I can implement it myself in my actual code.
You could take a flatMap approach for the recursive call of a flattening callback.
const
flat = ({ hostNames, children = [], ...o }) => [o, ...children.flatMap(flat)],
data = { countries: [{ name: "Denmark", id: "APA1", children: [{ name: "Zealand", id: "APA1.1", parentId: "APA1", children: [{ name: "Copenhagen", id: "APA1.1.1", parentId: "APA1.1", children: [{ name: "Dublin", id: "ANA1", parentId: "APA1.1.1.1", hostNames: [{ ip: "20.190.129.1" }, { ip: "20.190.129.2" }] }] }] }, { name: "Jutland", id: "APA1.2", parentId: "APA1", children: [{ name: "Nordjylland", id: "APA1.2.1", parentId: "APA1.2", children: [{ name: "Aalborg", id: "APA1.2.1.1", parentId: "APA1.2.1", children: [{ name: "Risskov", id: "ANA3", parentId: "APA1.2.1.1", hostNames: [{ ip: "40.101.81.146" }] }, { name: "Brabrand", id: "ANA4", parentId: "APA1.2.1.1", hostNames: [{ ip: "43.203.94.182" }] }] }] }] }] }] },
result = data.countries.flatMap(flat);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can combine the Array.flat() method and this answer to flatten objects recursively.
Using recursive functions is the faster way to accomplish that.
To get a flat structure you could use reduce method to create recursive function.
const data = {"countries":[{"name":"Denmark","id":"APA1","children":[{"name":"Zealand","id":"APA1.1","parentId":"APA1","children":[{"name":"Copenhagen","id":"APA1.1.1","parentId":"APA1.1","children":[{"name":"Dublin","id":"ANA1","parentId":"APA1.1.1.1","hostNames":[{"ip":"20.190.129.1"},{"ip":"20.190.129.2"}]}]}]},{"name":"Jutland","id":"APA1.2","parentId":"APA1","children":[{"name":"Nordjylland","id":"APA1.2.1","parentId":"APA1.2","children":[{"name":"Aalborg","id":"APA1.2.1.1","parentId":"APA1.2.1","children":[{"name":"Risskov","id":"ANA3","parentId":"APA1.2.1.1","hostNames":[{"ip":"40.101.81.146"}]},{"name":"Brabrand","id":"ANA4","parentId":"APA1.2.1.1","hostNames":[{"ip":"43.203.94.182"}]}]}]}]}]}]}
function flat(data) {
return data.reduce((r, { children, ...rest }) => {
if (children) r.push(...flat(children))
r.push(rest)
return r;
}, [])
}
const result = flat(data.countries)
console.log(result)
Currently I've got the following JSON feed:
var data = {
"feeds": {
"regions": [{
"name": "Lichtenberg",
"id": "01408.b",
"suburbs": [{
"name": "Fennpfuhl",
"views": 76400
},
{
"name": "Lichtenberg",
"views": 87895
},
{
"name": "Rummelsberg",
"views": 10239
}
]
},
{
"name": "Mitte",
"id": "03442.f",
"suburbs": [{
"name": "Tiergarten",
"views": 82695
},
{
"name": "Mitte",
"views": 67234
},
{
"name": "Hansaviertel",
"views": 10848
},
{
"name": "Moabit",
"views": 67500
}
]
},
{
"name": "Friedrichshain-Kreuzberg",
"id": "01991.o",
"suburbs": [{
"name": "Friedrichshain",
"views": "98494"
},
{
"name": "Kreuzberg",
"views": "27800"
}
]
},
{
"name": "Templehof-Schöneberg",
"id": "01778.k",
"suburbs": [{
"name": "Friedenau",
"views": 76595
},
{
"name": "Schöneberg",
"views": 20731
},
{
"name": "Templehof",
"views": 58000
},
{
"name": "Mariendorf",
"views": 32300
}
]
},
{
"name": "Pankow",
"id": "02761.q",
"suburbs": [{
"name": "Wießensee",
"views": 81294
},
{
"name": "Prenzlauer Berg",
"views": 76470
},
{
"name": "Pankow",
"views": 90210
}
]
}
],
}
};
Effectively I want to do two things:
Loop through the Regions to get the 4 names
Loop through all the views in each region, sum them up, and return them as values under the 4 names.
Here's a sample of the output that I just quickly typed up:
var viewsPerRegion =
[{
label: "Litchtenberg",
total: 174534
}, {
label: "Mitte",
total: 228277
}, {
label: "Friedrichshain-Kreuzberg",
total: 126294
}, {
label: "Templehof-Schöneberg",
total: 187626
}];
etc...
I do want to note that data.feeds.region[2].suburbs.views is stored as a string, so that's something I'll need to change into an integer first.
Anyway the solution I have so far (which doesn't really work) is as follows:
var viewsPerRegion, i, j, x;
for (i in data.feeds.regions) {
x += data.feeds.regions[i].name;
for (j in data.feeds.regions[i].suburbs.views){
x += data.feeds.regions[i].suburbs.views[j];
}
}
viewsPerRegion = x;
Any help is certainly appreciated - bit of a newbie in JSON and javascript.
You can map the regions array, extracting the name from each, and get the total by using reduce to add up each of the views:
const data={"feeds":{"regions":[{"name":"Lichtenberg","id":"01408.b","suburbs":[{"name":"Fennpfuhl","views":76400},{"name":"Lichtenberg","views":87895},{"name":"Rummelsberg","views":10239}]},{"name":"Mitte","id":"03442.f","suburbs":[{"name":"Tiergarten","views":82695},{"name":"Mitte","views":67234},{"name":"Hansaviertel","views":10848},{"name":"Moabit","views":67500}]},{"name":"Friedrichshain-Kreuzberg","id":"01991.o","suburbs":[{"name":"Friedrichshain","views":"98494"},{"name":"Kreuzberg","views":"27800"}]},{"name":"Templehof-Schöneberg","id":"01778.k","suburbs":[{"name":"Friedenau","views":76595},{"name":"Schöneberg","views":20731},{"name":"Templehof","views":58000},{"name":"Mariendorf","views":32300}]},{"name":"Pankow","id":"02761.q","suburbs":[{"name":"Wießensee","views":81294},{"name":"Prenzlauer Berg","views":76470},{"name":"Pankow","views":90210}]}],}}
const viewsPerRegion = data.feeds.regions.map(({ name, suburbs }) => ({
label: name,
total: suburbs.reduce((a, { views }) => a + Number(views), 0)
}));
console.log(viewsPerRegion);
As an example - I've included a one element array that contains an object that has a Children key, which is an array of objects and each object also has its' own Children key that contains another array.
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
{
"Id": "100",
"DisplayName": "1-2",
},
]
}
]
}
]
There is a second array of objects that I would like to compare the first array of objects to, with the intention of making sure that the first array is in the same order as the second array of objects, and if it is not - then sort until it is.
Here is the second array:
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "100",
"DisplayName": "1-2",
},
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
]
}
]
}
]
The data that this will run on can be up in the tens of thousands - so performance is paramount.
What I'm currently attempting is using a utility method to convert each element of the second array into a keyed object of objects e.g.
{
1: {
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}
]
}
}
This allows fast look up from the top level. I'm wondering if I should continue doing this all the way down or if there is an idiomatic way to accomplish this. I considered recursion as well.
The order of the already sorted array is not based on Id - it is arbitrary. So the order needs to be preserved regardless.
Assuming same depth and all Id's exist in each level of each object use a recursive function that matches using Array#findIndex() in sort callback
function sortChildren(main, other) {
other.forEach((o, i) => {
if (o.children) {
const mChilds = main[i].children, oChilds = o.children;
oChilds.sort((a, b) => {
return mChilds.findIndex(main => main.Id === a.Id) - mChilds.findIndex(main => main.Id === b.Id)
});
// call function again on this level passing appropriate children arrays in
sortChildren(mChilds, oChilds)
}
})
}
sortChildren(data, newData);
console.log(JSON.stringify(newData, null, ' '))
<script>
var data = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "3",
"DisplayName": "1-2",
},
{
"Id": "4",
"DisplayName": "3-4",
},
]
}]
}]
var newData = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}]
}]
</script>