Do I need to convert this Array in Objects? - javascript

My data is an array that I'm converting into a key:value (not sure if this is what it's called) type.
Data:
[
{
"id": 1,
"title": "Name 01",
"tags": [
"TAG1",
"TAG4",
"TAG2"
]
},
{
"id": 2,
"title": "Name 02",
"tags": [
"TAG4",
"TAG3"
]
},
{
"id": 3,
"title": "Name 03",
"tags": [
"TAG1"
]
}
]
I'm converting this into :
result = data.map(a => ({ [a.id]: a }));
So I'm getting:
Result:
[
{
"1": {
"id": 1,
"title": "Post1 T1 T2 T4",
"tags": [
"TAG1",
"TAG4",
"TAG2"
]
}
},
{
"2": {
"id": 2,
"title": "Post1 T3 T4",
"tags": [
"TAG4",
"TAG3"
]
}
},
{
"3": {
"id": 3,
"title": "Post3 with No Tags",
"tags": [
"TAG1"
]
}
}
]
How can I map the results and show in a View/Text?
I tried:
Object.keys(results).map((result, idx) => {
return(
<View key={idx}>
<Text>{result.title}</Text>
</View>
)
});
But I'm getting an error : Cannot read property 'map' of undefined.
Do I need to convert the results to an object and only then I'll be able to use Object.keys. If yes, how do I convert the entire result in an Object like this:
Results:
{
{
"1": {
"id": 1,
"title": "Post1 T1 T2 T4",
"tags": [
"TAG1",
"TAG4",
"TAG2"
]
}
},
{
"2": {
"id": 2,
"title": "Post1 T3 T4",
"tags": [
"TAG4",
"TAG3"
]
}
},
{
"3": {
"id": 3,
"title": "Post3 with No Tags",
"tags": [
"TAG1"
]
}
}
}
The reason I'm doing this is to target the id for a reducer dispatched action:
switch (action.type) {
case "INC_NUM":
const newState = {...state};
newState[action.payload].nubmer++;
return newState;

It sounds like you just want to be able to quickly find the object that has a given id value. Rather than "convert" your data, I'd suggest you just make a map so you can look up any object by id.
let data = [
{
"id": 1,
"title": "Name 01",
"tags": [
"TAG1",
"TAG4",
"TAG2"
]
},
{
"id": 2,
"title": "Name 02",
"tags": [
"TAG4",
"TAG3"
]
},
{
"id": 3,
"title": "Name 03",
"tags": [
"TAG1"
]
}
];
// create a map with id as the key, object as the value
let map = new Map();
data.forEach(obj => {
map.set(obj.id, obj);
});
// look up a given id
console.log(map.get(3));

Related

How to combine nested duplicate dictionary values within an array

I have a following data structure, array of dictionaries
[
{
"id": 1,
"name": "Some Name 1",
"topics": [
{
"id": 3,
"name": "Topic Name",
"topics": [],
},
{
"id": 3,
"name": "Topic Name",
"topics": [],
}
]
},
{
"id": 2,
"name": "Some Name 2",
"topics": [
{
"id": 3,
"name": "Topic Name",
"topics": [],
},
{
"id": 3,
"name": "Topic Name",
"topics": [],
}
]
},
[
{
"id": 1,
"name": "Some Name 2",
"topics": [
{
"id": 1,
"name": "Topic Name 1",
"topics": [],
},
{
"id": 2,
"name": "Topic Name 2",
"topics": [],
}
]
},
{
"id": 2,
"name": "Some Name 1",
"topics": [
{
"id": 3,
"name": "Topic Name",
"topics": [],
},
{
"id": 3,
"name": "Topic Name",
"topics": [],
}
]
},
I want to essentially be able to combine the arrays within each dictionary if I have the same id, so for each dictionary i will have higher level dictionary items being the same and essentially combine those together to avoid duplication. Preferably i would like it to be recursively being that in case the topics within topics are also duplicate (you can assume the order is always respected).
I would appreciate if you could share a solution to this

Group nested objects with reduce

I have an array with objects
const data = [{
"id": 19887003,
"category": "Shops",
"details": "Shoe Store",
"star": 2,
"subCategory": "Outlet",
},
{
"id": 19234003,
"category": "Shops",
"details": "Shoe Point",
"star": 2,
"subCategory": "Outlet",
},
{
"id": 190456003,
"category": "Food",
"details": "Korean",
"star": 4,
"subCategory": "Restaurant",
},
{
"id": 190111003,
"category": "Food",
"details": "Chinese",
"star": 4,
"subCategory": "Restaurant",
},
{
"id": 1902303,
"category": "Food",
"details": "Lounge",
"star": 4,
"subCategory": "Bar",
}]
this is a small piece but the structure is the same for all objects: i have a category, with multiple subcategories and sometimes the subcategory has details..for example the category food has the subcategory restourant and restourant has many types (chinese, korean).
My goal is to get a structure like that:
[
{
"category": "Food",
"subCategories": [
{
"Subcategory": "Bar",
"details": [
{
name: "Lounge",
star: 2,
id: 1902303
}
]
},
{
"Subcategory": "Restaurant",
"details": [
{
name: "Chinese",
star: 4,
id: 190111003
},
{
name: "Korean",
star: 4,
id: 190456003
}
]
}
},
{
"category": "Shops",
"subCategories": [
{
"Subcategory": "Outlet",
"details": [
{
name: "Shoe Store",
star: 2,
id: 19887003
},
{
name: "Shoe Point",
star: 2,
id: 19234003
}
]
}
]
}
]
My attempt:
const groupedCategories = data.reduce((accumulator, element) => {
const detail = element.details;
const category = element.category;
const subCategory = element.subCategory;
if (accumulator[category]){
return {
...accumulator,
[category]: {
...accumulator[category],
subCategories: [...new Set([...accumulator[category].subCategories,subCategory])],
}
}}
else {
return {
...accumulator,
[category]: {
subCategories: [subCategory],
}
}
}
}, {});
I tried use reduce method like that but this is not the exact structure I desire in particular how to put details fields into subcategories.
Thanks
array.reduce seems to be the right choice. Simplest approach is to have double if statement to check if previous element (category and subcategory exists) and either push into existing array or create new object on upper level:
const data = [{
"id": 19887003,
"category": "Shops",
"details": "Shoe Store",
"star": 2,
"subCategory": "Outlet",
},
{
"id": 19234003,
"category": "Shops",
"details": "Shoe Point",
"star": 2,
"subCategory": "Outlet",
},
{
"id": 190456003,
"category": "Food",
"details": "Korean",
"star": 4,
"subCategory": "Restaurant",
},
{
"id": 190111003,
"category": "Food",
"details": "Chinese",
"star": 4,
"subCategory": "Restaurant",
},
{
"id": 1902303,
"category": "Food",
"details": "Lounge",
"star": 4,
"subCategory": "Bar",
}]
let output = data.reduce((acc,cur) => {
let {category, subCategory, ...rest} = cur;
let prevCat = acc.find(x => x.category === category);
if(!prevCat){
acc.push({category, subCategories: [{subCategory, details: [rest]}]});
} else {
let prevSubCat = prevCat.subCategories.find(x => x.subCategory === subCategory);
if(!prevSubCat) {
prevCat.subCategories.push({subCategory, details: [rest]});
} else {
prevSubCat.details.push(rest);
}
}
return acc;
}, []);
console.log(output);

Merge two array of objects with nested id

I have two arrays of objects that I need to combine where the nested ID (connect.id) of the second array matches the id of the first but can't see how to do it
can anyone help?
const arr1 = [
{ "id": 7619209572755, "title": "Title 1" },
{ "id": 7619209157372, "title": "Title 2" },
{ "id": 7619209921625, "title": "Title 3" }
];
const arr2 = [
{
"id": 7619217289192,
"connect": [
{ "id": 7619209157372, "title": "Title 1" }
],
"value": "1"
},
{
"id": 7619217242206,
"connect": [
{ "id": 7619209921625, "title": "Title 2" }
],
"value": "2"
}
];
const expectedResult = [
{ "id": 7619209572755, "title": "Title 1" },
{ "id": 7619209157372, "title": "Title 2", "value": "1" },
{ "id": 7619209921625, "title": "Title 3", "value": "2" }
]
Using Array#reduce, iterate over arr2 to map every connect element's id with the its object's value in a Map
Using Array#map, iterate over arr1, if an element's id is in the map, set its value
const
arr1 = [ { "id": 7619209572755, "title": "Title 1" }, { "id": 7619209157372, "title": "Title 2" }, { "id": 7619209921625, "title": "Title 3" } ],
arr2 = [
{
"id": 7619217289192,
"connect": [ { "id": 7619209157372, "title": "Title 1" } ],
"value": "1",
},
{
"id": 7619217242206,
"connect": [ { "id": 7619209921625, "title": "Title 2" } ],
"value": "2",
}
];
const connectValueMap = arr2.reduce((map, { connect = [], value}) => {
connect.forEach(({ id }) => map.set(id, value));
return map;
}, new Map);
const merged = arr1.map(e => {
const value = connectValueMap.get(e.id);
if(value) e.value = value;
return e;
});
console.log(merged);

Need to modify BE response to expected response at FE

BE Response:- which I am getting from Backend Service
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
But I need to modify this response to as below on FE
Expected Response:- means I need to join name and description field text to one(in name field ) as below:-
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1-description1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1-subDescription1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1-subSubDesc1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2-description2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2-subDescription2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
there could be n number of children of each object and children can have an array of objects.
What I have done:- I am able to change the very first name but not children name
let resDataArry = [];
let descData: DynamicResource;
response.forEach((x, index) => {
const descName = x.name + ' ' + x.description;
descData = { ...tree.resources[index], name: descName };
resDataArry.push(descData);
});
return resDataArry;
Please help.
You can use nested Array#forEach to access children array and then concatenate the name and description together.
let data = {
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
data.data.resources.forEach(function(item){
item.name = item.name + ' ' + item.description;
item.children.forEach(function(child){
child.name = child.name + ' ' + child.description;
});
});
console.log(data);

Iterate through each object array based on condition check

I have a scenario were I need to iterate through each parent/child array in an object.
Each Grandparents can have multiple parents, in same fashion each parent can have multiple childs, each child can have multiple subChilds and so on.
I need to check if type is "parent" or "child" while iterating and then push name property to an array as mentioned in expected output.
Input Object:
var inputObject = {
"id": 1,
"name": "Grand Parent 1",
"type": "GrandParent",
"childType": [
{
"id": 2,
"type": "Parent",
"childType": [
{
"id": 3,
"type": "Child",
"childType": [],
"name": "Child 11"
},
{
"id": 4,
"type": "Child",
"childType": [],
"name": "Child 12"
}
],
"name": "Parent 1"
},
{
"id": 5,
"type": "Parent",
"childType": [
{
"id": 6,
"type": "Child",
"childType": [],
"name": "Child 21"
}
],
"name": "Parent 2"
},
{
"id": 7,
"type": "Parent",
"childType": [
{
"id": 8,
"type": "Child",
"childType": [],
"name": "Child 31"
}
],
"name": "Parent 3"
}
]
}
Code Tried:
function handleData({childType, ...rest}){
const res = [];
res.push(rest.name);
if(childType){
if(rest.type == "Child")
res.push(...handleData(childType));
}
return res;
}
const res = handleData(inputObject);
Expected Output:
If type selected is "Parent"
["Parent 1", "Parent 2, Parent 3"]
if type selected is "Child"
["Child 11", "Child 12", "Child 21", "Child 31"]
You can do a recursive function that uses flatMap():
const obj = {id:1,name:"Grand Parent 1",type:"GrandParent",childType:[{id:2,type:"Parent",childType:[{id:3,type:"Child",childType:[],name:"Child 11"},{id:4,type:"Child",childType:[],name:"Child 12"}],name:"Parent 1"},{id:5,type:"Parent",childType:[{id:6,type:"Child",childType:[],name:"Child 21"}],name:"Parent 2"},{id:7,type:"Parent",childType:[{id:8,type:"Child",childType:[],name:"Child 31"}],name:"Parent 3"}]};
const get = (o, t) => o.type === t ? [o.name] : o.childType.flatMap(c => get(c, t));
console.log(get(obj, 'GrandParent'));
console.log(get(obj, 'Parent'));
console.log(get(obj, 'Child'));
You can do that using recursion.
Steps:
Create a wrapper function in which you declare result array.
Inside that make a wrapper function create a function which would be called recursively
Check if type matches the given type add the name of object to result
Then check if elements exists in its childType. If yes yes then call function on each each of its element.
var inputObject = { "id": 1, "name": "Grand Parent 1", "type": "GrandParent", "childType": [ { "id": 2, "type": "Parent", "childType": [ { "id": 3, "type": "Child", "childType": [], "name": "Child 11" }, { "id": 4, "type": "Child", "childType": [], "name": "Child 12" } ], "name": "Parent 1" }, { "id": 5, "type": "Parent", "childType": [ { "id": 6, "type": "Child", "childType": [], "name": "Child 21" } ], "name": "Parent 2" }, { "id": 7, "type": "Parent", "childType": [ { "id": 8, "type": "Child", "childType": [], "name": "Child 31" } ], "name": "Parent 3" } ] }
function handleData(obj,type){
let res = [];
function recursive(obj){
if(type === obj.type) res.push(obj.name);
if(obj.childType.length){
obj.childType.forEach(a => recursive(a));
}
}
recursive(obj)
return res;
}
console.log(handleData(inputObject,"Child"))
console.log(handleData(inputObject,"Parent"))
Recursion is elegant but you could use es6 to do it , if the object childType was very large, recursion might not be applicable (stack overflow), here is a solution using reduce,
function getType({childType}, type) {
return childType.reduce( (acc, {type: objectType, name}) => {
if (objectType === type){
acc.push(name)
}
return acc
}, [])
}
You can solve this problem using recursion. You can try on this way !
var inputObject = {
"id": 1,
"name": "Grand Parent 1",
"type": "GrandParent",
"childType": [
{
"id": 2,
"type": "Parent",
"childType": [
{
"id": 3,
"type": "Child",
"childType": [],
"name": "Child 11"
},
{
"id": 4,
"type": "Child",
"childType": [],
"name": "Child 12"
}
],
"name": "Parent 1"
},
{
"id": 5,
"type": "Parent",
"childType": [
{
"id": 6,
"type": "Child",
"childType": [],
"name": "Child 21"
}
],
"name": "Parent 2"
},
{
"id": 7,
"type": "Parent",
"childType": [
{
"id": 8,
"type": "Child",
"childType": [],
"name": "Child 31"
}
],
"name": "Parent 3"
}
]
};
var resultValues = [];
function getResult(inputObject, propertyName, propertyValue) {
for (var objectProperty in inputObject) {
if (objectProperty == propertyName && inputObject[objectProperty] == propertyValue) {
resultValues.push(inputObject['name']);
console.log(resultValues);
} else {
if (objectProperty == 'childType') {
inputObject[objectProperty].forEach(function (element) {
getResult(element, propertyName, propertyValue)
});
}
}
}
//console.log(resultValues);
}
getResult(inputObject, 'type', 'GrandParent');
getResult(inputObject, 'type', 'Parent');
getResult(inputObject, 'type', 'Child');

Categories