Reputation: 13206
I have the following array of objects below (components) and I want to remove all the null entries. How can I go about doing it? I am trying the following:
static deleteNullComponents(components) {
return components.filter(function (el) {
return el['components'] != null;
});
}
but I get the error: TypeError: components.filter is not a function
. How can I fix it?
[
{
"components": [
null,
{
"componentId": "navbar-zJNm0HaP",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
null,
null,
{
"componentId": "features-MJU8gcYR",
"componentIndex": 5,
"componentName": "app-builder-features",
},
null,
{
"componentId": "features-2hsUdwaT",
"componentIndex": 7,
"componentName": "app-builder-features",
},
null,
{
"componentId": "footer-dLvoLZ16",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "Home"
},
{
"components": [
null,
{
"componentId": "navbar-UBdYplVp",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
{
"componentId": "features-mmEzByeO",
"componentIndex": 3,
"componentName": "app-builder-features"
},
null,
{
"componentId": "features-GZKgh9lV",
"componentIndex": 5,
"componentName": "app-builder-features"
},
null,
{
"componentId": "footer-IyrNODRQ",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "About"
}
]
Upvotes: 0
Views: 90
Reputation: 91
You're only stepping one layer into that object. Assuming that you don't care about the name property you need something like:
// take the array of objects and iterate over them
firstLevelArray.map((secondLevelArray) => {
// grab each components array in the array of objects, and filter it for null
return secondLevelArray['components'].filter((possibleComponent) => {
return possibleComponent != null;
})
});
However you probably want to keep the name, and in any case this is a pretty rigid way to do things as you're assuming your current data structure. Here's a quick and dirty recursive method, which should handle an arbitrary number of nestings... however recursion isn't fully properly implemented in javascript. You SHOULD be using a library like underscore for deep comparison. I wrote this up for fun and to be illustrative, as reading library code can be somewhat difficult if you're new to javascript (and even then for my little brain).
Though it's likely already clear, what we're doing here is stepping into each item in your json, checking if it's null, if not then if it's an array or an object: visit each item of that, and so on.
let deepRemoveNull = function(x) {
if (x === null) {
return;
}
if (Array.isArray(x)) {
let arr = [];
for (const i of x) {
if (x !== null) {
let result = deepRemoveNull(i);
// get rid of undefined
if (result) {
arr.push(result);
}
}
}
return arr;
} else if (typeof x === 'object') {
let obj = {};
for (const key in x) {
if (x[key] !== null) {
let result = deepRemoveNull(x[key]);
// get rid of undefined
if (result) {
obj[key] = result;
}
}
}
return obj;
}
return x;
}
If you pass in your object to the function above it should work for you. DO NOT USE THE ABOVE IN PRODUCTION CODE
Upvotes: 1
Reputation: 1
You could use a one-liner :
components = components.filter(function(el) { return el !== null });
Upvotes: -2
Reputation: 1
components
are an array property inside an array items in pageComponents
So you'll need two loops (forEach/map/filter etc are really just iterating through an array)
So, for each item in the pageComponents
array, you want to filter values in the components
property of that item
Also, in the filter function, you don't need to return the original array, since you are not altering the original array, you are altering a nested array within it
class MyService {
static deleteNullComponents(components) {
components.forEach(obj =>
obj.components = obj.components.filter(item => item !== null)
)
}
}
let pageComponents = [
{
"components": [
null,
{
"componentId": "navbar-zJNm0HaP",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
null,
null,
{
"componentId": "features-MJU8gcYR",
"componentIndex": 5,
"componentName": "app-builder-features",
},
null,
{
"componentId": "features-2hsUdwaT",
"componentIndex": 7,
"componentName": "app-builder-features",
},
null,
{
"componentId": "footer-dLvoLZ16",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "Home"
},
{
"components": [
null,
{
"componentId": "navbar-UBdYplVp",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
{
"componentId": "features-mmEzByeO",
"componentIndex": 3,
"componentName": "app-builder-features"
},
null,
{
"componentId": "features-GZKgh9lV",
"componentIndex": 5,
"componentName": "app-builder-features"
},
null,
{
"componentId": "footer-IyrNODRQ",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "About"
}
]
MyService.deleteNullComponents(pageComponents)
console.log(pageComponents)
Upvotes: 1
Reputation: 3745
Looks like you are running filter on the wrong object, try the following:
NOTE: This will also modify the original components array that is passed into the deleteNullComponents
, so it is unnecessary to re-assign components after the method call. If you don't want this behavior, take a look at the following thread:
How to deep clone an object in Javascript
class MyService {
static deleteNullComponents(components) {
return components.map(obj =>
obj["components"].filter(item => item !== null)
)
}
}
let pageComponents = [
{
"components": [
null,
{
"componentId": "navbar-zJNm0HaP",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
null,
null,
{
"componentId": "features-MJU8gcYR",
"componentIndex": 5,
"componentName": "app-builder-features",
},
null,
{
"componentId": "features-2hsUdwaT",
"componentIndex": 7,
"componentName": "app-builder-features",
},
null,
{
"componentId": "footer-dLvoLZ16",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "Home"
},
{
"components": [
null,
{
"componentId": "navbar-UBdYplVp",
"componentIndex": 1,
"componentName": "app-builder-navbar",
},
null,
{
"componentId": "features-mmEzByeO",
"componentIndex": 3,
"componentName": "app-builder-features"
},
null,
{
"componentId": "features-GZKgh9lV",
"componentIndex": 5,
"componentName": "app-builder-features"
},
null,
{
"componentId": "footer-IyrNODRQ",
"componentIndex": 9,
"componentName": "app-builder-footer",
},
null
],
"name": "About"
}
]
// no need to re-assign here, the original object is modified
pageComponents = MyService.deleteNullComponents(pageComponents)
console.log(pageComponents)
Upvotes: 1