Related
My question relates to the fact I'm querying 2 different objects from DB and the result is in JSON. I need to merge them into one.
The 2 objects have in common this two key/value IRBId = ... and id = ... and they look as an example
OBJ 1
{
"data":{
"IRBs":{
"nodes":[
{
"id":"8",
"name":"Admin ",
},
{
"id":"9",
"name":"Again",
}
],
}
}
}
OBJ 2
{
"data":{
"informedConsentForms":{
"count":3,
"nodes":[
{
"id":"93",
...
"IRBId":"9",
},
{
"id":"92",
...
"IRBId":"8",
},
{
"id":"91",
...
"IRBId":"8",
}
],
}
},
As you will see above OBJ 2 and OBJ 1 corresponding with the same at IRBid and id.
What I need is to merge the two OBJ where IRBId OBJ 2 === id OBJ 1
The result I would expect after the merge is
OBJ merged
{
[{
"id":"93",
...
"IRBId":"9",
"irb": {
"name":"Again ",
...
}
},
{
"id":"92",
...
"IRBId":"8",
"irb": {
"name":"Admin ",
...
}
},
{
"id":"91",
...
"IRBId":"8",
"irb": {
"name":"Admin ",
...
}
],
},
I don't know how to make it looks like this.
Try using Array.reduce
Logic
Loop through second object data nodes
Find the matching nodes from object 1 data nodes.
Push to accumulator with required details. (I have added only the nodes that was mentioned in in Expected resut, you can add asmuch as you need.)
const obj1 = {
"data": {
"IRBs": {
"nodes": [
{
"id": "8",
"name": "Admin ",
},
{
"id": "9",
"name": "Again",
}
],
}
}
}
const obj2 = {
"data": {
"informedConsentForms": {
"count": 3,
"nodes": [
{
"id": "93",
"IRBId": "9",
},
{
"id": "92",
"IRBId": "8",
},
{
"id": "91",
"IRBId": "8",
}
],
}
},
};
const obj1List = obj1.data.IRBs.nodes;
const output = obj2.data.informedConsentForms.nodes.reduce((acc, curr) => {
const matchingNode = obj1List.find((item) => item.id === curr.IRBId);
if (matchingNode) {
acc.push({
id: curr.id,
IRBId: curr.IRBId,
irb: {
name: matchingNode.name
}
})
}
return acc;
}, []);
console.log(output);
You need to use the map function on the nodes in the first object to construct a new object that contains the second and first object's attributes.
const obj1 = {
"data": {
"IRBs": {
"nodes": [{
"id": "8",
"obj1": "one",
"name": "Admin ",
},
{
"id": "9",
"obj1": "two",
"name": "Again",
}
]
}
}
};
const obj2 = {
"data": {
"informedConsentForms": {
"count": 3,
"nodes": [{
"id": "93",
"obj2": "1",
"IRBId": "9",
},
{
"id": "92",
"obj2": "2",
"IRBId": "8",
},
{
"id": "91",
"obj2": "3",
"IRBId": "8",
}
],
}
}
};
const obj1Data = obj1.data.IRBs.nodes;
const obj2Data = obj2.data.informedConsentForms.nodes;
const res = obj2Data.map(item => {
const obj1Item = obj1Data.find(obj1Item => item.IRBId === obj1Item.id);
return obj1Item ? { ...item, "irb": { ...obj1Item}} : { ...item};
});
console.log(res);
i am using nested loop, try this one
const obj2 = {
"data":{
"informedConsentForms":{
"count":3,
"nodes":[
{
"id":"93",
"IRBId":"9",
},
{
"id":"92",
"IRBId":"8",
},
{
"id":"91",
"IRBId":"8",
}
],
}
},
}
const obj1 = {
"data":{
"IRBs":{
"nodes":[
{
"id":"8",
"name":"Admin ",
},
{
"id":"9",
"name":"Again",
}
],
}
}
}
const result = [];
const obj2Nodes = obj2.data.informedConsentForms.nodes;
for(let i = 0; i < obj2Nodes.length; i++) {
const obj1Nodes = obj1.data.IRBs.nodes
for(let j = 0; j < obj1Nodes.length; j++) {
if(obj2Nodes[i].IRBId === obj1Nodes[j].id) {
const {id, ...reObj1Nodes} = obj1Nodes[j];
result.push({
...obj2Nodes[i],
'irb': {
...reObj1Nodes
}
})
}
}
}
console.log(result)
Json:( How to iterate this array of arrays using map function.. I have tried this.. In this.materialList => array i am getting only 1 st array of values 2nd and 3rd array values are getting undefined.. so i am not able to display in html.. )
subrecipes:[
subrecipematerials: [
"id": 1
"material_id": {
"id":1,
"title":"cookies"
}
],
[
"id": 2
material_id: {
"id":2,
"title":"cake"
}
]
subrecipeformulations: [
"id": 1,
"formula_id": {
"id":1,
"title":formula1
}
]
]
subrecipes:[
subrecipematerials: [
"id": 1
material_id: {
"id":1,
"title":"cookies"
}
],
[
"id": 2
material_id: {
"id":2,
"title":"cake"
}
]
subrecipeformulations: [
"id": 1,
"formula_id": {
"id":1,
"title":formula1
}
]
]
component.ts(I have tried this.. In this.materialList => array i am getting only 1 st array of values 2nd and 3rd array values are getting undefined.. so i am not able to display in html.. )
let subrecipeMaterials = this.data.subRecipes.map((item, index) => {
item = item.subrecipeMaterials[index]
return item
})
let tempMatList1 = this.group_By_Data(subrecipeMaterials, "sub_recipe_id")
let matSubrecipies = Object.keys(tempMatList1).map(data => tempMatList1[data])
this.filterMaterials(matSubrecipies)
this.subrecipies = matSubrecipies.map((data, index) => {
return {
matList: this.materialList[index],
formList: this.otherFormulationList[index],
subRec: (index + 1)
}
})
group_By_Data(arr, key) {
return arr.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
}
filterMaterials(matSubrecipies) {
this.materialList = matSubrecipies.map(sub => {
return sub.filter(mat => {
let checkmat_id = mat.material_id
if (!!checkmat_id) }
return mat.material_id
}
})
})
}
getMaterialListArray(i) {// this function used to display this array through html.. right now only i am getting 1st array..
return this.materialList[i]
}
Your data is not correct. I think it should be in the form:
{subrecipes:[{
subrecipematerials: [{
"id": 1,
"material_id": {
"id":1,
"title":"cookies"
},
},
{
"id": 2,
material_id: {
"id":2,
"title":"cake"
}
}],
subrecipeformulations: [{
"id": 1,
"formula_id": {
"id":1,
"title":"formula1"
}
}]
},
{
subrecipematerials: [{
"id": 1,
material_id: {
"id":1,
"title":"cookies"
}
},
{
"id": 2,
material_id: {
"id":2,
"title":"cake"
}
} ] ,
subrecipeformulations: [{
"id": 1,
"formula_id": {
"id":1,
"title":"formula1"
}
}]
}]
};
Also, the code item = item.subrecipeMaterials[index] should be item = item.subrecipematerials[index] (difference is M and m as it is case sensitive).
let data = {
"rec": [{
"id": "25837",
"contentId": "25838"
},
{
"id": "25839",
"contentId": "25838"
},
{
"id": "25838"
},
{
"id": "25636",
"contentId": "25837"
}, {
"id": "25640",
"contentId": "25839"
}
]
};
I have a javascript object which I have to manipulate to below format.
{
"childern": [{
"id": "25838",
"childern": [{
"id": "25837",
"contentId": "25838",
"childern": [{
"id": "25636",
"contentId": "25837"
}]
},
{
"id": "25839",
"contentId": "25838",
"childern": [{
"id": "25640",
"contentId": "25839"
}]
}
]
}]
}
If any object dont have contentId it should be at parent level. then all the objects having contentId same as parent id should be at its child level and so on.
I have created a fiddle here but logic is not completed. Any idea or reference to achieve this.
You could create recursive function with reduce method to get the desired result.
let data = {"rec":[{"id":"25837","contentId":"25838"},{"id":"25839","contentId":"25838"},{"id":"25838"},{"id":"25636","contentId":"25837"},{"id":"25640","contentId":"25839"}]}
function nest(data, pid) {
return data.reduce((r, e) => {
if (pid == e.contentId) {
const obj = { ...e }
const children = nest(data, e.id);
if (children.length) obj.children = children
r.push(obj)
}
return r;
}, [])
}
const result = nest(data.rec);
console.log(result[0])
I have a JSON Structure something like:
[
{
"name":"angelinas"
},
{
"name":"besuto"
},
{
"name":"catch",
"cuisine":"Japanese"
},
{
"name":"center cut"
},
{
"name":"fedora"
},
{
"name":"Habanero",
"cuisine":"Mexican"
},
{
"name":"Indies"
},
{
"name":"new"
},
{
"name":"RazINN"
},
{
"name":"restaurantTestVenue779"
},
{
"name":"restaurantTestVenue9703"
},
{
"name":"Salsa ",
"cuisine":"Mexican"
},
{
"name":"Sushi Place",
"cuisine":"Japanese"
},
{
"name":"The Ashoka"
},
{
"name":"The Poboys"
},
{
"name":"the shogun"
},
{
"name":"vinyard view"
}
]
Using the JSON above i want to identify whether a cuisine is assosiated to restaurant. If yes, I want to build a JSON Structure something like:
[
{
"Mexican":{
"venueNames":[
"Habanero",
"Salsa"
]
}
},
{
"Japanese":{
"venueNames":[
"Sushi Place",
"catch"
]
}
}
]
Have tried to build the JSON using a for loop and .hasProperty but not much of a success.
Here is what you can do!
First iterate through the data and use the method "hasOwnProperty" to check if the cuisine exists and if it does then check if your cuisines object has that cuisine and if does then add it to it.
const data = [{
"name": "angelinas"
},
{
"name": "besuto"
},
{
"name": "catch",
"cuisine": "Japanese"
},
{
"name": "center cut"
},
{
"name": "fedora"
},
{
"name": "Habanero",
"cuisine": "Mexican"
},
{
"name": "Indies"
},
{
"name": "new"
},
{
"name": "RazINN"
},
{
"name": "restaurantTestVenue779"
},
{
"name": "restaurantTestVenue9703"
},
{
"name": "Salsa ",
"cuisine": "Mexican"
},
{
"name": "Sushi Place",
"cuisine": "Japanese"
},
{
"name": "The Ashoka"
},
{
"name": "The Poboys"
},
{
"name": "the shogun"
},
{
"name": "vinyard view"
}
]
let cuisines = {};
for (const resturant of data) {
if (resturant.hasOwnProperty('cuisine')) {
if (cuisines.hasOwnProperty(resturant.cuisine)) {
cuisines[resturant.cuisine].venueNames.push(resturant.name);
} else {
cuisines[resturant.cuisine] = {
venueNames: [resturant.name]
};
}
}
}
You can use in one loop below.
data.forEach(function(item) {
// if item has cuisine and cuisine not exist in new array
if(item["cuisine"] != null && typeof newArr.find(v => v[item.cuisine] != null) == 'undefined') {
// create new object with structure
let obj = {};
obj[item.cuisine] = {
"venueNames":[item.name]
};
newArr.push(obj);
}
else {
// else find existing cuisine and add new venue
let obj = newArr.find(v => v.hasOwnProperty(item.cuisine));
if(typeof obj != 'undefined') {
obj[item.cuisine].venueNames.push(item.name);
}
}
});
JSFIDDLE
It's a simple reduction of the array. If the restaurant has a defined cuisine, check if the result already has this cuisine defined. If not, create an object for it where you can push the restaurant name to.
const restaurants = [
{
"name":"angelinas"
},
{
"name":"besuto"
},
{
"name":"catch",
"cuisine":"Japanese"
},
{
"name":"center cut"
},
{
"name":"fedora"
},
{
"name":"Habanero",
"cuisine":"Mexican"
},
{
"name":"Indies"
},
{
"name":"new"
},
{
"name":"RazINN"
},
{
"name":"restaurantTestVenue779"
},
{
"name":"restaurantTestVenue9703"
},
{
"name":"Salsa ",
"cuisine":"Mexican"
},
{
"name":"Sushi Place",
"cuisine":"Japanese"
},
{
"name":"The Ashoka"
},
{
"name":"The Poboys"
},
{
"name":"the shogun"
},
{
"name":"vinyard view"
}
];
const cuisines = restaurants.reduce((result, restaurant ) => {
if ( restaurant.hasOwnProperty( 'cuisine' )) {
const { cuisine } = restaurant;
if ( !result.hasOwnProperty( cuisine )) {
result[ cuisine ] = {
venueNames: []
};
}
result[ cuisine ].venueNames.push( restaurant.name );
}
return result;
}, {});
console.log( cuisines );
In my personal opinion, I would use a slightly different structure though. If we represent collections with objects that are always the same, we can simplify most transformations. This is less efficient that doing everything in one loop, but the code used to create the transformation is almost readable english:
const restaurants = [
{ "name": "angelinas", "cuisine": null },
{ "name": "besuto", "cuisine": null },
{ "name": "catch", "cuisine": "japanese" },
{ "name": "center cut", "cuisine": null },
{ "name": "fedora", "cuisine": null },
{ "name": "habanero", "cuisine": "mexican" },
{ "name": "Indies", "cuisine": null },
{ "name": "new", "cuisine": null },
{ "name": "RazINN", "cuisine": null },
{ "name": "restaurantTestVenue779", "cuisine": null },
{ "name": "restaurantTestVenue9703", "cuisine": null },
{ "name": "Salsa ", "cuisine": "mexican" },
{ "name": "Sushi Place", "cuisine": "japanese" },
{ "name": "The Ashoka", "cuisine": null },
{ "name": "The Poboys", "cuisine": null },
{ "name": "the shogun", "cuisine": null },
{ "name": "vinyard view", "cuisine": null }
];
const create_cuisine = name => ({ name, "venues": [] });
const unique = () => {
const seen = {};
return item => {
const json = JSON.stringify( item );
return seen.hasOwnProperty( json )
? false
: ( seen[ json ] = true );
};
};
// Filter away all the restaurants without a cuisine value.
const restaurants_with_cuisine = restaurants.filter( restaurant => restaurant.cuisine );
const cuisines = restaurants_with_cuisine
// Extract the cuisine anmes from the restaurants.
.map( restaurant => restaurant.cuisine )
// Filter aways all the duplicates.
.filter( unique() )
// Create a new cuisine object.
.map( cuisine_name => create_cuisine( cuisine_name ));
// Finally add all the restaurant names to the right cuisine.
restaurants_with_cuisine.forEach( restaurant => cuisines.find( cuisine => cuisine.name === restaurant.cuisine ).venues.push( restaurant.name ));
console.log( cuisines );
Using a few es6 features, we can generate this list with Set, map and filter.
We will first map a list of cuisines, and remove invalid ones such as undefined. With that we will use a Set to create a unique list of cuisines.
Next we will take that list and map it again to return the final object, by filtering the original object where the cuisine matches the current iteration. Finally we map the filtered results to return just the name to the venueNames object.
Our result will look like this:
function getItems(places) {
// Get a unique list of cuisines
return [...new Set(places.map(p => p.cuisine).filter(c => c))]
// Build the result
.map(c => {
return {
[c]: {
// Get a list of cuisines that match the current cuisine
venueNames: places.filter(p => p.cuisine == c).map(c => c.name)
}
}
})
}
const places = [
{"name": "angelinas"},
{"name": "besuto"},
{"name": "catch","cuisine": "Japanese"},
{"name": "center cut"},
{"name": "fedora"},
{"name": "Habanero","cuisine": "Mexican"},
{"name": "Indies"},
{"name": "new"},
{"name": "RazINN"},
{"name": "restaurantTestVenue779"},
{"name": "restaurantTestVenue9703"},
{"name": "Salsa ","cuisine": "Mexican"},
{"name": "Sushi Place","cuisine": "Japanese"},
{"name": "The Ashoka"},
{"name": "The Poboys"},
{"name": "the shogun"},
{"name": "vinyard view"}
]
console.log(getItems(places))
I am trying to return all objects that have a specific 'id' in the nested array. In the sample data, I'd like to return all person objects with hobbies id of 2 (hiking).
The other question addresses the problem of finding all values in an array based on an object value.
This question differs from the previous because I need to return all objects based on a value inside of a nested array.
[
{
"id":111222,
"name":"Faye",
"age":27,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":3,
"name":"eating"
}
]
},
{
"id":223456789001,
"name":"Bobby",
"age":35,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":4,
"name":"online gaming"
}
]
}
]
function hasHobby(person, hobbyId) {
return person.hobbies.some(function(hobby) {
return hobby.id === hobbyId;
});
}
function filterByHobby(people, hobbyId) {
return people.filter(function(person) {
return hasHobby(person, hobbyId);
});
}
If you wanna use the new cool ES6 syntax:
function filterByHobby(people, hobbyId) {
return people.filter(
person => person.hobbies.some(
hobby => hobby.id === hobbyId
)
);
}
var arr = [
{
"id":111222,
"name":"Faye",
"age":27,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":3,
"name":"eating"
}
]
},
{
"id":223456789001,
"name":"Bobby",
"age":35,
"hobbies":[
{
"id":2,
"name":"hiking"
},
{
"id":4,
"name":"online gaming"
}
]
}
];
arr.filter(function(obj) {
var hobbies = obj.hobbies;
var x = hobbies.filter(function(hob) {
if (hob.id == "2") return true;
});
if (x.length > 0) return true;
});
Try this, I think its solve your proble:
var arr = [{
"id": 111222,
"name": "Faye",
"age": 27,
"hobbies": [{
"id": 2,
"name": "hiking"
}, {
"id": 3,
"name": "eating"
}]
}, {
"id": 223456789001,
"name": "Bobby",
"age": 35,
"hobbies": [{
"id": 2,
"name": "hiking"
}, {
"id": 4,
"name": "online gaming"
}]
}];
var x = arr.filter(function(el) {
var rnel = el.hobbies.filter(function(nel) {
return nel.id == 2;
});
return rnel.length > 0 ? true :false;
});
alert(x.length);