lodash create new json object from existing one - javascript

I want to delete and rename some props of my existing JSON Object to use it with select2/select2 query plugins
My JSON object that i need to transform is:
[
{
"id": 1,
"type": "Subject1",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"Tags": [
{
"id": 1,
"name": "sub1",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"tagType": 1
}
]
},
{
"id": 2,
"type": "Subject2",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"Tags": [
{
"id": 16,
"name": "sub2",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"tagType": 2
}
]
},
{
"id": 3,
"type": "Subject3",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"Tags": [
{
"id": 22,
"name": "sub3",
"createdAt": "2016-02-19T23:03:12.000Z",
"updatedAt": "2016-02-19T23:03:12.000Z",
"tagType": 3
}
]
}
]
To
[
{
"text": "Subject1",
"children": [
{
"id": 1,
"text": "sub1"
}
]
},
{
"text": "Subject2",
"children": [
{
"id": 16,
"text": "sub2"
}
]
},
{
"text": "Subject3",
"children": [
{
"id": 22,
"text": "sub3"
}
]
}
]
I need to :
rename name and type to text
delete tagType, updatedAt and createdAt
rename Tags to children
remove the id of each top objects
Is there a way to do all this using lodash ?
What the best way?

var res = _.map(items, function(item){
return {
text: item.type,
children: _.map(item.Tags, function(tag){
return {
id: tag.id,
text: tag.name
};
})
};
});

I succed using this link by nesting two return :
Creating new javascript Object form existing one
var result = tags.map(function(obj) {
return {
text: obj.type,
childrens:obj.Tags.map(function(obj) {
return {
id : obj.id,
text : obj.name
}
})
};
});

Related

create array on basis of object's child

I am have array like:
[
{
"_id": "62434e4c52a870a3840f40fd",
"Nome": [
{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Oo",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"Peso": [
{
"_id": "61f92ec87a308dd136c0e182",
"value": "554",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"createdAt": [
{
"value": "29/03/2022 03:22:02"
}
]
},
{
"_id": "62449de6ed196e40cb4309ae",
"Nome": [
{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Ssg",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"Peso": [
{
"_id": "61f92ec87a308dd136c0e182",
"value": "255",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"createdAt": [
{
"value": "29/03/2022 03:23:26"
}
]
},
],
What I'm having trouble with is loop between each object example Nome, Peso the names of these arrays are dynamic and do not have a static name!
Example of what I'm thinking:
[
{
"_id": "62434e4c52a870a3840f40fd",
"Nome": "Oo",
"Peso": "554",
"createdAt": "29/03/2022 03:22:02"
},
{
"_id": "62449de6ed196e40cb4309ae",
"Nome": "Ssg",
"Peso": "255",
"createdAt": "29/03/2022 03:23:26"
}
],
Thanks for help :D
If each Nome, Peso, createdAt property array always has one element, then you can use Array#map as follow:
const input = [ { "_id": "62434e4c52a870a3840f40fd", "Nome": [ { "_id": "61f76c3c7a308dd136f1d33a", "value": "Oo", "updatedAt": "2022-05-04T00:00:00.000Z" } ], "Peso": [ { "_id": "61f92ec87a308dd136c0e182", "value": "554", "updatedAt": "2022-05-04T00:00:00.000Z" } ], "createdAt": [ { "value": "29/03/2022 03:22:02" } ] }, { "_id": "62449de6ed196e40cb4309ae", "Nome": [ { "_id": "61f76c3c7a308dd136f1d33a", "value": "Ssg", "updatedAt": "2022-05-04T00:00:00.000Z" } ], "Peso": [ { "_id": "61f92ec87a308dd136c0e182", "value": "255", "updatedAt": "2022-05-04T00:00:00.000Z" } ], "createdAt": [ { "value": "29/03/2022 03:23:26" } ] } ];
const output = input.map(({_id,...rest}) => ({
_id,
...Object.fromEntries(
Object.entries(rest).map(([k,v]) => [k,v[0].value])
)
}));
console.log( output );
If considering those dynamic keys will have array then try below code.
const data = [{
"_id": "62434e4c52a870a3840f40fd",
"Nome": [{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Oo",
"updatedAt": "2022-05-04T00:00:00.000Z"
}],
"Peso": [{
"_id": "61f92ec87a308dd136c0e182",
"value": "554",
"updatedAt": "2022-05-04T00:00:00.000Z"
}],
"createdAt": [{
"value": "29/03/2022 03:22:02"
}]
},
{
"_id": "62449de6ed196e40cb4309ae",
"Nome": [{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Ssg",
"updatedAt": "2022-05-04T00:00:00.000Z"
}],
"Peso": [{
"_id": "61f92ec87a308dd136c0e182",
"value": "255",
"updatedAt": "2022-05-04T00:00:00.000Z"
}],
"createdAt": [{
"value": "29/03/2022 03:23:26"
}]
},
];
data.map(d => {
Object.keys(d).forEach(k => {
if (Array.isArray(d[k]) && d[k].length > 0)
d[k] = d[k][0].value;
});
});
console.log(data);
The below may be one possible solution to achieve the desired objective.
Code Snippet
const transformArr = arr => (
arr.map(obj => ({
...Object.fromEntries(
Object.entries(obj)
.map(([k, v]) => {
if (v && v.length > 0 &&
Array.isArray(v) &&
"value" in v[0]
) {
return [k, v[0].value]
} else {
return [k, v]
}
})
)
}))
);
const origArr = [
{
"_id": "62434e4c52a870a3840f40fd",
"Nome": [
{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Oo",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"Peso": [
{
"_id": "61f92ec87a308dd136c0e182",
"value": "554",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"createdAt": [
{
"value": "29/03/2022 03:22:02"
}
]
},
{
"_id": "62449de6ed196e40cb4309ae",
"Nome": [
{
"_id": "61f76c3c7a308dd136f1d33a",
"value": "Ssg",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"Peso": [
{
"_id": "61f92ec87a308dd136c0e182",
"value": "255",
"updatedAt": "2022-05-04T00:00:00.000Z"
}
],
"createdAt": [
{
"value": "29/03/2022 03:23:26"
}
]
},
];
console.log(transformArr(origArr));
Explanation
Iterate over the array
Use Object.entries() and Object.fromEntries() to extract key-value [k, v]pairs (as arrays) and then re-create (key-value pairs array back into an) object
Check if v is an array and that it has an element at index-0 with a prop value
If yes, then transform it to show only the value (of index-0 element)
Otherwise, just return v as-is
Constraint
If the inner-array (for "Nome", "Peso" or other "dynamic keys") has more than one element only the value from index-0 element will be considered.
NOTE
This solution does not mutate the original-array. It creates a new copy & if needed this may be re-assigned to the original-array.

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);

Normalizr: normalize deep nested items

I have an array of data like this one
[
{
"id": "root_01",
"parents": [
{
"id": "parent_1",
"childrens": [
{
"id": "child_01",
"name": "ABC",
"group": "group_a"
},
{
"id": "child_02",
"name": "BBC",
"group": "group_b"
}
]
},
{
"id": "parent_2",
"childrens": [
{
"id": "child_03",
"name": "CCD",
"group": "group_a"
},
{
"id": "child_04",
"name": "EEF",
"group": "group_c"
}
]
}
]
},
{} // same as previous
]
and I'm trying to get rid of all parents data & catch & merge only child items like this one:
[
{
"id": "child_01",
"name": "ABC",
"group": "group_a"
},
{
"id": "child_02",
"name": "BBC",
"group": "group_b"
},
{
"id": "child_03",
"name": "CCD",
"group": "group_a"
},
{
"id": "child_04",
"name": "EEF",
"group": "group_c"
}
]
but after reading normalizr documentation I'm a little bit confused because I couldn't find this kind of example, so can anyone suggest me is it possible to make with normalizr or any better idea?
Thanks
Recusrion is what you need here:
const arr = [ { "id": "root_01", "parents": [ { "id": "parent_1", "childrens": [ { "id": "child_01", "name": "ABC", "group": "group_a" }, { "id": "child_02", "name": "BBC", "group": "group_b" } ] }, { "id": "parent_2", "childrens": [ { "id": "child_03", "name": "CCD", "group": "group_a" }, { "id": "child_04", "name": "EEF", "group": "group_c" } ] } ] }];
const flatten = arr => arr.flatMap(o=>o.parents ? flatten(o.parents) : o.childrens ? flatten(o.childrens) : o);
console.log(flatten(arr));

How to match array with comma seperated values in Javascript?

I have two arrays, one for categories and other for products. Products contain multiple categories as a comma-separated string. Now I want to match a particular category and add the matched product to an array to each category.
I want to match the category to product_category.
Here are the arrays
Products
[
{
"id": 1,
"product_title": "Product 1",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Shirts,Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-08T11:42:15.000Z"
},
{
"id": 4,
"product_title": "Product 2",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-10T07:08:23.000Z"
}
]
Categories
[
{
"id": 1,
"category_name": "Shirts",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
},
{
"id": 9,
"category_name": "Pents",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
}
]
Code that I try but not working
this.categories.forEach(cat => {
this.products.filter(prod => {
if (prod.product_category.split(',').indexOf(cat.category_name) !== -1) {
this.categories.push(prod);
}
});
});
Please help me to solve this issue.
Any solution appreciated!
You could use .map() on categories to add a products property to it. This property will be the result of a .filter() on the products.
const categoriesWithProducts = categories.map(cat => {
return {
...cat,
products: products.filter(prod => {
return prod.product_category.split(',').includes(cat.category_name);
})
};
});
``
One of the approaches is to create a new array where you would push products mapped to specific categories:
var products = [
{
"id": 1,
"product_title": "Product 1",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Shirts,Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-08T11:42:15.000Z"
},
{
"id": 4,
"product_title": "Product 2",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-10T07:08:23.000Z"
}
];
var categories = [
{
"id": 1,
"category_name": "Shirts",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
},
{
"id": 9,
"category_name": "Pents",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
}
]
var productCategories = [];
categories.forEach((cat)=> {
var productCategory = {};
productCategory.category = cat;
productCategory.products = [];
products.forEach(prod => {
if (prod.product_category.indexOf(cat.category_name) !== -1) {
productCategory.products.push(prod);
}
});
productCategories.push(productCategory);
console.log(productCategories);
});
You do not need filter(), you can use another forEach() with includes() and Object.assign():
var products = [
{
"id": 1,
"product_title": "Product 1",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Shirts,Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-08T11:42:15.000Z"
},
{
"id": 4,
"product_title": "Product 2",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-10T07:08:23.000Z"
}
];
var categories = [
{
"id": 1,
"category_name": "Shirts",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
},
{
"id": 9,
"category_name": "Pents",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
}
]
categories.forEach((cat,i) => {
products.forEach(prod => {
if (prod.product_category.split(',').includes(cat.category_name)) {
Object.assign(categories[i], prod);
}
});
});
console.log(categories);
You can use Array#filter to filter products on catagory names using Array#some
let products = [{"id":1,"product_title":"Product 1","product_size":null,"product_author":5,"description":"Test Description","product_category":"Shirts,Pents,Salwar","createdAt":"2020-02-08T11:42:15.000Z","updatedAt":"2020-02-08T11:42:15.000Z"},{"id":4,"product_title":"Product 2","product_size":null,"product_author":5,"description":"Test Description","product_category":"Pents,Salwar","createdAt":"2020-02-08T11:42:15.000Z","updatedAt":"2020-02-10T07:08:23.000Z"}]
let catagories = [{"id":1,"category_name":"Shirts","createdAt":"2020-02-08T04:59:59.000Z","updatedAt":"2020-02-10T06:50:05.000Z"},{"id":9,"category_name":"Pents","createdAt":"2020-02-08T04:59:59.000Z","updatedAt":"2020-02-10T06:50:05.000Z"}]
let catagoryNames = new Set(catagories.map(e => e.category_name));
let filtered = [...products].filter(e => e.product_category.split(',').some(cat => catagoryNames.has(cat)));
console.log(filtered)
Try this
categories.forEach(function(c){
c.products=products.filter(function(p){
var reg=new RegExp(c.category_name,'gi');
return reg.test(p.product_category)
})
})
Without Regex
categories.forEach(function(c){
c.products=products.filter(function(p){
return (p.product_category.split(',').indexOf(c.category_name)!==-1)
})
})
You will get the products inside each category
Fiddle here
Try this code.I hope it will helps you.
product = [
{
"id": 1,
"product_title": "Product 1",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Shirts,Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-08T11:42:15.000Z"
},
{
"id": 4,
"product_title": "Product 2",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-10T07:08:23.000Z"
}
]
categories=[
{
"id": 1,
"category_name": "Shirts",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z",
},
{
"id": 9,
"category_name": "Pents",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z",
}
]
this.categories.forEach(cat => {
cat['product'] = []
this.product.filter(prod => {
if (prod.product_category.split(',').indexOf(cat.category_name) !== -1) {
cat['product'].push(prod);
}
});
});
console.log(this.categories)
You can easily loop through all categories and then loop throgh all products. For each product check if category name is present and if so add product to category products:
this.categories.forEach(cat => {
cat.products = [];
this.products.forEach(prod => {
if (prod.product_category.split(',').indexOf(cat.category_name) !== -1) {
cat.products.push(prod);
}
});
});
Please note that I changed filter to forEach.
const products = [
{
"id": 1,
"product_title": "Product 1",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Shirts,Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-08T11:42:15.000Z"
},
{
"id": 4,
"product_title": "Product 2",
"product_size": null,
"product_author": 5,
"description": "Test Description",
"product_category": "Pents,Salwar",
"createdAt": "2020-02-08T11:42:15.000Z",
"updatedAt": "2020-02-10T07:08:23.000Z"
}
];
const categories = [
{
"id": 1,
"category_name": "Shirts",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
},
{
"id": 9,
"category_name": "Pents",
"createdAt": "2020-02-08T04:59:59.000Z",
"updatedAt": "2020-02-10T06:50:05.000Z"
}
];
const matchedProducts = [];
products.map(prod=>{
const isCateoryMatched = categories.some(c=>{
return prod.product_category.includes(c.category_name)
});
if(isCateoryMatched ){
matchedProducts.push(prod);
}
})
//if you want to push the matched products into categories
categories.push(...matchedProducts)
console.log('matchedProducts',matchedProducts);
console.log('categories',categories);

Do I need to convert this Array in Objects?

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));

Categories