I'm building a component that allows me to compare two objects. It accepts a list of fields to compare and a list of fields that need to be ignored in string format
Here is an example of the object that will be compared:
{
// (..... More elements above .....)
taskData: {
"uniqueId": "OrdenTrabajo48",
"id": 48,
"position": 1,
"name": "Dirección Obra Civil",
"description": "Dirección Obra Civil Afecta: Sorda, Roberto",
"startDate": "2021-10-16T11:00:00.000Z",
"endDate": "2022-06-01T11:00:00.000Z",
"duration": 227,
"progress": 73,
"hours": 0,
"realHours": 15,
"predecessor": null,
"child": [],
"resourceInfo": [
{
"uniqueId": "Persona_1MJ0VE9G0",
"id": "OrdenTrabajo48Persona_1MJ0VE9G0",
"name": "Sorda, Roberto",
"group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
"unit": 4.1667,
"startDate": "2021-10-16T03:00:00.000+00:00",
"endDate": "2022-06-01T02:59:59.000+00:00",
"hours": 0,
"realHours": 15,
"avatar": "http://localhost:8091/images/llama.jpg"
}
],
"comments": null,
"etiquetas": [],
"baseLineStartDate": null,
"baseLineEndDate": null
}
// (..... More elements below .....)
}
(But to clarify, it could be any object. The component is abstract and can be used anywhere)
The component doesn't know the structure of the object to compare, just the object and the paths in string format
I want to remove in every element of the array resourceInfo, the properties avatar, icon, label and color regardless the length of the array, but I don't know if there is a syntax to do that.
Also I want to remove the property realHours
This is what I tried:
const ignoredFields = [
'taskData.resourceInfo[?].avatar', //<--- It's not working
'taskData.resourceInfo[].icon', //<--- Neither this
'taskData.resourceInfo.label', //<--- Or this
'taskData.resourceInfo[0].color', //<--- This hardcode is working, but I don't know the length in that scope
'taskData.realHours' // <-- No problems here
];
const currentComparableObject = _.omit(obj, ignoredFields);
const oldComparableObject = _.omit(prev, ignoredFields);
var fieldsToOmit=[];
var resourceInfoFields=['avatar','icon','label','color'];
var globalFields=['realHours'];
taskData.resourceInfo.forEach((item,index)=>{
resourceInfoFields.forEach((field)=>{
fieldsToOmit.push(`resourceInfo[${index}].${field}`)
})
})
console.log( _.omit(taskData, fieldsToOmit.concat(globalFields)))
You do not need lodash to delete fields from an array. I mean you can if you really want to but, it is trivial to loop through the array and delete the fields you want.
#Yasser CHENIK isn't wrong just doesn't do a good job of explaining the solution.
Below I have included a thorough example so you can test for yourself.
NOTE this solution mutates the original array but, it is not difficult to use this concept to make an immutable version.
const taskData = {
"uniqueId": "OrdenTrabajo48",
"id": 48,
"position": 1,
"name": "Dirección Obra Civil",
"description": "Dirección Obra Civil Afecta: Sorda, Roberto",
"startDate": "2021-10-16T11:00:00.000Z",
"endDate": "2022-06-01T11:00:00.000Z",
"duration": 227,
"progress": 73,
"hours": 0,
"realHours": 15,
"predecessor": null,
"child": [],
"resourceInfo": [
{
"uniqueId": "Persona_1MJ0VE9G0",
"id": "OrdenTrabajo48Persona_1MJ0VE9G0",
"name": "Sorda, Roberto",
"group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
"unit": 4.1667,
"startDate": "2021-10-16T03:00:00.000+00:00",
"endDate": "2022-06-01T02:59:59.000+00:00",
"hours": 0,
"realHours": 15,
"avatar": "http://localhost:8091/images/llama.jpg"
},
{
"uniqueId": "Persona_1MJ0VE9G0",
"id": "OrdenTrabajo48Persona_1MJ0VE9G0",
"name": "Sorda, Roberto",
"group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
"unit": 4.1667,
"startDate": "2021-10-16T03:00:00.000+00:00",
"endDate": "2022-06-01T02:59:59.000+00:00",
"hours": 0,
"realHours": 15,
"avatar": "http://localhost:8091/images/llama.jpg"
},
{
"uniqueId": "Persona_1MJ0VE9G0",
"id": "OrdenTrabajo48Persona_1MJ0VE9G0",
"name": "Sorda, Roberto",
"group": "Subgerencia de Planes y Proyectos - SUB_PLAN_PROY_SIT",
"unit": 4.1667,
"startDate": "2021-10-16T03:00:00.000+00:00",
"endDate": "2022-06-01T02:59:59.000+00:00",
"hours": 0,
"realHours": 15,
"avatar": "http://localhost:8091/images/llama.jpg"
},
],
"comments": null,
"etiquetas": [],
"baseLineStartDate": null,
"baseLineEndDate": null
}
const fieldsToOmit = [
'avatar',
'icon',
'label',
'color',
'realHours'
]
console.log(taskData.resourceInfo);
taskData.resourceInfo.forEach(info => {
fieldsToOmit.forEach(field => {
delete info[field];
})
});
console.log(taskData.resourceInfo);
You can remove properties in a functional manner (immutable) by using destructuring:
const {realHours, ...result} = {
...taskData,
resourceInfo: taskData.resourceInfo.map(
({avatar, icon, label, color, ...keep}) => keep
)
};
console.log(result);
Thanks for the answers to all.
To solve partially the problem, I created a function that does the following:
It filters the references that contains [?] (i.e: taskData.resourceInfo[?].avatar)
Then obtain the first part of the string (That is, the path to reach the array) and the second part (property name)
Using _.get from lodash it retrieves the length of the array and creates a new fieldReference with the index, so loadash can read it.
private sanitizeArrays(obj: any, fieldReferences: string[]): string[] {
const fieldsDup = [...fieldReferences];
// Get Elements that contains [?] in the property name
const arrays = fieldsDup.filter(ignoredField => ignoredField.match(/\[\?]/g));
// Remove elements that contain [?] from ignoredFieldsDuplicated
fieldsDup.forEach((ignoredField, index) => {
if (ignoredField.includes('[?]')) {
fieldsDup.splice(index, 1);
}
});
// Get the properties names without [?]
const arrayPropertyName = arrays.map(ignoredField => ignoredField.split('[')[0]);
const afterArrayPropertyName = arrays.map(ignoredField => ignoredField.split(']')[1]);
// For each array that I have...
arrayPropertyName.forEach((array, index) => {
const length = _.get(obj, array).length;
for (let i = 0; i < length; i++) {
fieldsDup.push(array + '[' + i + ']' + afterArrayPropertyName[index]);
}
});
return fieldsDup;
}
Example input (if the object contains only one element in resourceInfo):
'taskData.resourceInfo[?].avatar',
'taskData.resourceInfo[?].icon',
'taskData.resourceInfo[?].label',
'taskData.resourceInfo[?].color',
'taskData.resourceInfo[?].fontColor',
'taskData.realHours'
Example output:
taskData.resourceInfo[?].icon
taskData.resourceInfo[?].color
taskData.realHours
taskData.resourceInfo[0].avatar
taskData.resourceInfo[0].icon
taskData.resourceInfo[0].label
taskData.resourceInfo[0].color
taskData.resourceInfo[0].fontColor
(javascript includes() isn't playing nice deleting the [?])
Also it doesn't work for nested arrays...
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 1 year ago.
I wanted to map all the names and power of the objects and if he finds an array inside gadgets he would add +1 (i++), how would that be?
The list is much bigger, but I just show these two
"list": [
{
"name": "SHELLY",
"power": 10,
"gadgets": [
{
"id": 23000255,
"name": "FAST FORWARD"
}
]
},
{
"name": "COLT",
"power": 7,
"gadgets": [
{
"id": 23000273,
"name": "SPEEDLOADER"
},
{
"id": 23000319,
"name": "SILVER BULLET"
}
]
]
}
A simple map should do it:
const data = {list:[{name:"SHELLY",power:10,gadgets:[{id:23000255,name:"FAST FORWARD"}]},{name:"COLT",power:7,gadgets:[{id:23000273,name:"SPEEDLOADER"},{id:23000319,name:"SILVER BULLET"}]}]};
const res = data.list.map(p => ({
name: p.name,
power: p.power + p.gadgets.length
}));
console.log(res);
l know my question is similar for too many questions. l have checked all answers and all answers are not give me what l want exactly.
l have this array :
[
{
"size": true,
"status": true,
"desc": "صحن مخلمة",
"name": "مخلمة",
"id": "QmzeJgg2F2"
}
]
l want to push new array object by index array above using this code :
items_local: any[] = [];
add_addons(index,data) {
this.items_local[index].addons.push(data.addons);
console.log(this.items_local);
}
expected output :
[
{
"addons": [ // new array pushing
{
"price": 10
},
{
"price": 10
}
],
"size": true,
"status": true,
"desc": "صحن مخلمة",
"name": "مخلمة",
"id": "QmzeJgg2F2"
}
]
Error :
ERROR TypeError: Cannot read property 'push' of undefined
your original object doesn't have a addons key, hence you can't call the push property on it, first create that key and assign to empty array
add_addons(index,data) {
this.items_local[index].addons = []
this.items_local[index].addons.push(data.addons);
console.log(this.items_local);
}
This question already has answers here:
How to count duplicate value in an array in javascript
(35 answers)
Closed 5 years ago.
I have a JSON file. I want to find the length of the JSON object where one key-value pair is similar. Like,
https://api.myjson.com/bins/h5mgv
[
{
"receive_date": "2013-11-04",
"responses": "2",
"name": "west"
},
{
"receive_date": "2013-11-04",
"responses": "8668",
"name": "west"
},
{
"receive_date": "2013-11-13",
"responses": "121",
"name": "east"
}
]
In the above example, length is 2 where "name": "west" and length is 1 where "name": "east" . I want to iterate through the JSON and find the identical values for the key name using Javascript. Output should look like,
east : 1
west : 2
By using length() I can find the length of whole JSON but what is recommended way to find the length for identical key values.
You can use reduce to get a new object listing the count of each name:
const myArray = [
{
"receive_date": "2013-11-04",
"responses": "2",
"name": "west"
},
{
"receive_date": "2013-11-04",
"responses": "8668",
"name": "west"
},
{
"receive_date": "2013-11-13",
"responses": "121",
"name": "east"
}
]
const myCounts = myArray.reduce((counts, item) => {
if (counts[item.name] === undefined) counts[item.name] = 0;
counts[item.name]++;
return counts;
}, {});
console.log(myCounts);
This produces the result:
{
"west": 2,
"east": 1
}
This question already has answers here:
How to filter object array based on attributes?
(21 answers)
Closed 6 years ago.
I have a json array like this
[
{"Id":1,
"Name":"John"
},
{"Id":2,
"Name":"Mathew"
},
{"Id":3,
"Name":"Wilfred"
},
{"Id":4,
"Name":"Gary"
}
]
I need to implement an auto complete feature using this data.
so if I search for "Wil" I should get Wilfred as result. How can I do such a search similar to the SQL LIKE in JSON array
Use Array.prototype.filter
var persons = [{
"Id": 1,
"Name": "John"
}, {
"Id": 2,
"Name": "Mathew"
}, {
"Id": 3,
"Name": "Wilfred"
}, {
"Id": 4,
"Name": "Gary"
}]
var searchTerm = "Wil";
var results = persons.filter(function(person) {
return person.Name.indexOf(searchTerm) > -1;
});
console.log(results);