ES6 Check property value in deep nested dynamic object - javascript

My data set:
{
courseID003: {
studentID34: {
assigned: false
dueDate: null
}
studentID34: {
assigned: false
dueDate: null
}
}
courseID007: {
studentID89: {
assigned: true
dueDate: "2018-12-07 15:51"
}
studentID111: {
assigned: true
dueDate: "2018-12-07 15:51"
}
studentID115: {
assigned: false
dueDate: null
}
}
}
Question:
I have a number of course objects that contain student objects. Each course could contain a different number of students.
I need to search every course and every student to see if the assigned property is set to true.
Ideally, I'd like to call a function that performs this search and simply returns true or false. When searching, as soon as an assigned property is found set to true, the search would exit and return true. If all assigned properties are set to false for every student in every course, then return false.
I hope this question makes sense and I hope the data set makes sense/properly formatted ( I am dealing with all objects -- no arrays). All the course objects are in an object.
Thanks in advance for any help!

Here you are!
const data = {
courseID003: {
studentID34: {
assigned: false,
dueDate: null
},
studentID34: {
assigned: false,
dueDate: null
}
},
courseID007: {
studentID89: {
assigned: true,
dueDate: "2018-12-07 15:51"
},
studentID111: {
assigned: true,
dueDate: "2018-12-07 15:51"
},
studentID115: {
assigned: false,
dueDate: null
}
}
}
const search = (data) => {
return Object.keys(data).some(courseKey => {
return Object.keys(data[courseKey]).some(studentKey => {
return data[courseKey][studentKey]['assigned']
})
})
}
console.log(search(data))
Reference: some, Object.keys

You're going to have a bad time searching through that data as written. The real issue is your choice of data structure. In two places, you are using an object when you should be using an array.
Here is the same data but with courses encoded as an array, which is traversable with the rich set of array methods. I've made the same change to the collection of students for each course.
let courses = [
{
id: 'courseID003',
students: [
{
id: 'studentID34',
assigned: false,
dueDate: null
},
{
id: 'studentID34',
assigned: false,
dueDate: null
}
]
},
{
id: 'courseID007',
students: [
{
id: 'studentID89',
assigned: true,
dueDate: "2018-12-07 15:51"
},
{
id: 'studentID111',
assigned: true,
dueDate: "2018-12-07 15:51"
},
{
id: 'studentID115',
assigned: false,
dueDate: null
}
]
}
];
let unassignedStudents = Array.prototype.concat.apply(
[],
courses.map(c => c.students.filter(s => !s.assigned)));
console.log('unassignedStudents:',unassignedStudents);
With this improved data structure, you can find all 'unassigned' students like this:
let unassignedStudents = Array.prototype.concat.apply(
[],
courses.map(c => c.students.filter(s => !s.assigned)));
Hopefully you can see how this change in structure opens new doors for you.
Good luck.

This should do the trick, keep in mind Object.values might require a polyfill (for IE) as well as flatMap (missing in many browsers atm).
const courses = Object.values(data);
const students = courses.flatMap(course => Object.values(course);
const result = students.some(student => student.assigned);

Related

How to filter array objects?

Trying to filter an array of objects based on an object returned by user, returning a new array. I've tried everything I could. Can't get what others have posted to work either because I need to check every object value to be either matching or undefined in the user object (undefined means user has no preference, lets say). Here is what I have come up with, three functions. None of these functions work. Even one working solution is great, but if someone has time to explain why the rest don't work that would be a bonus. This should return the Ford Mustang object. Also have to figure out how to specify a range of numbers, for the zeroSixty. I'm a beginner, having issues with syntax.
const carArray = [
{
brand: 'Mazda',
model: '3',
trim: 'base',
year: 2022,
drive: ['FWD', 'AWD'],
LKA: true,
laneCenter: false,
handsFree: false,
style: 'sedan',
zeroSixty: 7.5
},
{
brand: 'Ford',
model: 'Mustang Mach E',
trim: 'base',
year: 2022,
drive: ['FWD', 'AWD'],
LKA: true,
laneCenter: true,
handsFree: true,
style: 'SUV',
zeroSixty: 3.7
},
{
brand: 'KIA',
model: 'Forte',
trim: 'GT',
year: 2022,
drive: ['FWD'],
LKA: true,
laneCenter: true,
handsFree: false,
style: 'sedan',
zeroSixty: 6.4
},
]
const userCar =
{
brand: undefined,
model: undefined,
trim: undefined,
year: 2022,
drive: undefined,
LKA: true,
laneCenter: true,
handsFree: undefined,
style: 'SUV',
zeroSixty: undefined
};
const result = carArray.filter(x => userCar.some(y => (x.Object.values(carArray) === y.Object.values(userCar)) || (y.Object.values(userCar) === undefined)));
console.log(result);
const condensedCarFilter = (userCar, carArray) => {
return carArray.filter(obj => {
return obj.values.every(feature => {
return ((userCar.values.includes(feature) === true) || (userCar.values.includes(feature) === undefined));
})
})
};
let contensedTest = condensedCarFilter(userCar, carArray);
console.log(condensedTest);
const findCar = (userCar, carArray) => {
filteredArray = [];
for (x =0; x < carArray.length; x++) {
if ((Object.values(carArray[x]) === Object.values(userCar)) || (Object.values(userCar) === undefined)) {
filteredArray.push(carArray[x])
console.log(Object.values(carArray[x]));
}
}
console.log(filteredArray);
};
findCar(userCar, carArray);
I've created a jsfiddle you can look at here: https://jsfiddle.net/rlouie/6osq9kgn/1/
With the criteria you specified, this works:
function filterToDefinedAndMatching(car) {
return Object.entries(car).every(([key, value]) => !userCar[key] || userCar[key] == value);
}
const matchingCars = carArray.filter(filterToDefinedAndMatching);
However, you will run into problems once you want to match on drive, since it is an array. Array equality is by reference not value, and it won't match, so you need even more:
function betterFilterToMatchCars(car) {
return Object.entries(car).every(([key, value]) => {
const userCarValue = userCar[key];
if (Array.isArray(userCarValue)) {
return userCarValue.every(item => value.includes(item));
} else {
return !userCarValue || userCarValue == value;
}
});
}
If your car object keeps getting more complex, you really just need a more generic deep equals check, which you can find more about here:
Object comparison in JavaScript

JS says an object is undefined even though it shows with console.log

As the title states, my JS says an object is undefined even though if I console.log the parent it shows. I'm using prisma, but all that does is return a list of the objects containing {id, title, user:{id, name}}.
Code:
const userProjects = await prisma.projectMembers.findMany({
where: {
userId: token._id
},
select: {
project: {
select: {
id: true,
title: true,
user: {
select: {
id: true,
name: true,
},
},
},
},
},
});
userProjects.map(project => {
console.log(project)
console.log(project.user)
return {
id: project.id,
title: project.title,
user: project.user.id,
}
})
Output:
As you can see in the screenshot, there's a nested project property, and the user property is inside that. So project.user should be project.project.user.
userProjects.map(project => {
console.log(project)
console.log(project.project.user)
return project.project;
})
There's no need for you to create your own object when returning, since it's the same as project.project.

How to fix an error when working with an array and the find method?

I have a question about working with the find method. I have a task - I need to go through the array and find a match with a specific string. But at the same time there is a condition that this string can be inside one of the objects already in its child array. I make an if construct in my function to check this when passing through the array, but it does not work out as I expected. Tell me, please, where I went wrong.
P.S. I write more correctly. If the array object "newList" has "items" , then you need to look for comparison not in the object, but in its "items" array among "role" . If "items" does not exist for the object, then we look for a match in this object among "role"
const newList = [
{
role: "role111",
title: "title1",
},
{
role: "role222",
title: "title2",
},
{
role: "role333",
title: "title3",
},
{
role: "role444",
title: "title4",
items: [{
role: "role555",
title: "title5",
}, {
role: "role666",
title: "title6",
}, {
role: "role777",
title: "title7",
},]
},
{
role: "role888",
title: "title8",
},
];
const url = "role7";
export const findAfterRefresh = (list, url) =>
list.find((item) => {
if (item.items && item.items?.length > 0) {
return item.items.find((childrenITem) => childrenITem.role.includes(url));
}
return item.role.includes(url);
});
;
findAfterRefresh(newList, url);
Your solution was close, but if you call find on newList, it can only ever return one of the elements of newList, it can't return an element from the items array of one of those elements. That plus the fact you want the role value, not the element itself, makes the find method not a good match for your current data structure (but keep reading; if you really want to use find, there's a way).
Instead, a simple loop with recursion does the job:
/*export*/ const findAfterRefresh = (list, url) => {
for (const item of list) {
if (item.role?.includes(url)) {
return item.role;
}
if (item.items?.length) {
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
return childRole;
}
}
}
};
Here's a version with explanatory comments:
/*export*/ const findAfterRefresh = (list, url) => {
// Loop the given list...
for (const item of list) {
// ...check this item's role
// (Remove v-- this `?` if `role` will always be there)
if (item.role?.includes(url)) {
return item.role;
}
// If this item has child items, check them
if (item.items?.length) {
// Search child items using recursion
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
// Found it, return it
return childRole;
}
// Didn't find it, keep looping
}
}
};
Live Example:
const newList = [
{
role: "role1",
title: "title1",
},
{
role: "role2",
title: "title2",
},
{
role: "role3",
title: "title3",
},
{
role: "role4",
title: "title4",
items: [
{
role: "role5",
title: "title5",
},
{
role: "role6",
title: "title6",
},
{
role: "role7plusotherstuff",
title: "title7",
},
],
},
];
/*export*/ const findAfterRefresh = (list, url) => {
// Loop the given list...
for (const item of list) {
// ...check this item's role
// (Remove v-- this `?` if `role` will always be there)
if (item.role?.includes(url)) {
return item.role;
}
// If this item has child items, check them
if (item.items?.length) {
// Search child items using recursion
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
// Found it, return it
return childRole;
}
// Didn't find it, keep looping
}
}
};
console.log("Searching for 'role7'");
console.log(findAfterRefresh(newList, "role7"));
console.log("Searching for 'role2'");
console.log(findAfterRefresh(newList, "role2"));
Note: I added a bit to the role containing role7 so you could see that the code returns the full role, not just the bit in url.
But if you really want to use find, you can do it by first creating a flat array of roles:
// Creates a new array of `role` values (the array may also contain
// `undefined`, if the `role` property of any element or child element is
// `undefined`)
const flattenRoles = (list) =>
(list ?? []).flatMap((item) => [item.role, ...flattenRoles(item.items)]);
/*export*/ const findAfterRefresh = (list, url) => {
return flattenRoles(list).find((role) => role?.includes(url));
};
That code's a big shorter, but note that it creates a number of temporary arrays, and it always works its way through the full list before looking for roles, whereas the earlier version stops looking as soon as it's found a matching role. That's unlikely to be a problem if newList is of a reasonable size, but it's worth keeping in mind. (I'd probably use the earlier version, not this.)
Here's that in action:
const newList = [
{
role: "role1",
title: "title1",
},
{
role: "role2",
title: "title2",
},
{
role: "role3",
title: "title3",
},
{
role: "role4",
title: "title4",
items: [
{
role: "role5",
title: "title5",
},
{
role: "role6",
title: "title6",
},
{
role: "role7plusotherstuff",
title: "title7",
},
],
},
];
// Creates a new array of `role` values (the array may also contain
// `undefined`, if the `role` property of any element or child element is
// `undefined`)
const flattenRoles = (list) =>
(list ?? []).flatMap((item) => [item.role, ...flattenRoles(item.items)]);
/*export*/ const findAfterRefresh = (list, url) => {
return flattenRoles(list).find((role) => role?.includes(url));
};
console.log("Searching for 'role7'");
console.log(findAfterRefresh(newList, "role7"));
console.log("Searching for 'role2'");
console.log(findAfterRefresh(newList, "role2"));
In a comment you've asked:
ESLint: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.(no-restricted-syntax)
...how much do you think eslnit is right in this case?
That's up to you. If your target environment is ES2015+, there's no need for regenerator-runtime. As far as I know, there are no major pre-ES2015+ environments (IE11 is obsolete and discontinued). But if you need to support it and want to avoid regenerator-runtime, you can replace the for-of loop with some and assigning to a closed-over variable:
const newList = [
{
role: "role1",
title: "title1",
},
{
role: "role2",
title: "title2",
},
{
role: "role3",
title: "title3",
},
{
role: "role4",
title: "title4",
items: [
{
role: "role5",
title: "title5",
},
{
role: "role6",
title: "title6",
},
{
role: "role7plusotherstuff",
title: "title7",
},
],
},
];
/*export*/ const findAfterRefresh = (list, url) => {
// Loop the given list...
let role;
list.some((item) => {
// ...check this item's role
// (Remove v-- this `?` if `role` will always be there)
if (item.role?.includes(url)) {
role = item.role;
return true;
}
// If this item has child items, check them
if (item.items?.length) {
// Search child items using recursion
const childRole = findAfterRefresh(item.items, url);
if (childRole) {
// Found it, return it
role = childRole;
return true;
}
// Didn't find it, keep looping
}
});
return role;
};
console.log("Searching for 'role7'");
console.log(findAfterRefresh(newList, "role7"));
console.log("Searching for 'role2'");
console.log(findAfterRefresh(newList, "role2"));
The return true; statements tell some that you're done, it can stop looping.
...and the error on childRole from typescript is TS7022: 'childRole' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
The TypeScript error is just because the code doesn't have type annotations, because it was a JavaScript question, not a TypeScript question. :-) If you add the appropriate type annotations, it'll be fine.
As per my understanding, You are trying to filtered out the newList with all the objects includes role7 string in role property either in main object or in the child array objects. If Yes, You have to use Array.filter() method instead of Array.find() as it will only returns the first element in the provided array that satisfies the provided testing function.
Live Demo :
const newList = [
{
role: "role111",
title: "title1",
},
{
role: "role777",
title: "title2",
},
{
role: "role333",
title: "title3",
},
{
role: "role444",
title: "title4",
items: [{
role: "role555",
title: "title5",
}, {
role: "role666",
title: "title6",
}, {
role: "role777",
title: "title7",
},]
},
{
role: "role888",
title: "title8",
},
];
const url = "role7";
const findAfterRefresh = (list, url) =>
list.filter((item) => {
return (item.role.includes(url)) ? item :
item.items = item.items?.filter((childrenITem) => childrenITem.role.includes(url));
});
console.log(findAfterRefresh(newList, url));
After reading some of the other solutions I was able to refactor my code down a little bit. I decided to convert the raw array value into a 2d array, each nested array value would hold the role and item values.
I chose to do things this way so that the output of this function can still be used for any purpose regarding the roles and titles of these items. and to create an array which would be easy to iterate through.
const url = "role6";
const findAfterRefresh = (list) =>{
let foundData = []
list.find((item) => {
foundData.push([item.role, item.title]);
if (item.items !== undefined) {
item.items.find((item) => {
foundData.push([item.role, item.title]);
})
}
});
return foundData
}
for(let v in findAfterRefresh(newList) ){
if (findAfterRefresh(newList)[v].includes(url)) {
console.log(findAfterRefresh(newList)[v].includes(url)); break
}
}
//output of findAfterRefresh: [[role1,title1],[role2,title2][... etc
//ouput of the for loop at the bottom: true...
Ok I got to it.
Edit: I didn't read the title carefully, the code at the bottom is with for instead of "find" I hope it's not a problem
const newList = [
{
role: "role1",
title: "title1",
},
{
role: "role2",
title: "title2",
},
{
role: "role3",
title: "title3",
},
{
role: "role4",
title: "title4",
items: [{
role: "role5",
title: "title5",
}, {
role: "role6",
title: "title6",
}, {
role: "role7",
title: "title7",
},]
}
];
const url = "role2";
const findAfterRefresh = (list, url) => {
for(const singleItem of Object.values(list)) {
if(singleItem.items && singleItem.items?.length > 0) {
return singleItem.items.find(child => child.role === url);
};
if(!singleItem.role.includes(url)) {
continue;
};
return singleItem;
}
};
findAfterRefresh(newList, url);

How does one create custom filter conditions for array items upon ever newly computed query-data?

I have a filter object that is returned by query params
url = /all?channels=calls,text&calls=voicemail,missed
const query = {
channels: 'calls,texts',
calls: 'voicemail,missed',
};
I then have an array of objects that come in from a socket.
const arr = [
{
id: 1,
channel: 'SMS',
sent: '2021-08-22T03:21:18.41650+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
direction: 'INBOUND',
},
{
id: 2,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: false,
voicemail: true,
},
direction: 'INBOUND',
},
{
id: 3,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: true,
voicemail: false,
},
direction: 'INBOUND',
},
{
id: 4,
channel: 'VOICE',
sent: '2021-08-20T23:15:56.00000+0000',
sender: {
contactType: 'business',
},
recipients: [
{
contactType: 'corporate',
},
],
callDetails: {
answered: false,
voicemail: false,
},
direction: 'INBOUND',
},
];
I want to filter out the objects that match the filters but the query obj isn't friendly enough to just map the arr through.
With the query obj shared above, i should return the objects id:1 and id:2 and id:4 from arr, since those object meet the criteria of sms, voicemail, & missed
I assume i need a modified query obj that has to have various conditions available for each property, i.e calls: voicemail === callDetails.voicemail === true or calls: received === callDetails.answered === true
I've seen lots of examples on how to filter an array of objects with multiple match-criteria, but with the req of the property having multiple conditions, i've hit a wall.
thanks for the help
The main idea is to provide kind of a rosetta stone which does bridge/map the query specific syntax with any list item's specific data structure. Thus one will end up writing a map which takes a query's structure into account but ensures for each necessary query endpoint an item specific filter condition/function.
The query function should simply filter the item list by applying a list of logical OR conditions, thus using some for returning the boolean filter value.
Which leaves one of implementing a helper method which collects ... via Object.entries and Array.prototype.flatMap as well as via String.prototype.split and Array.prototype.map ... the function endpoints from the above introduced requirements configuration/map, based on the query object, provided by the system. Thus this helper might be named resolveQuery.
const sampleList = [{
id: 1,
channel: 'SMS',
direction: 'INBOUND',
}, {
id: 2,
channel: 'VOICE',
callDetails: {
answered: false,
voicemail: true,
},
direction: 'INBOUND',
}, {
id: 3,
channel: 'VOICE',
callDetails: {
answered: true,
voicemail: false,
},
direction: 'INBOUND',
}, {
id: 4,
channel: 'VOICE',
callDetails: {
answered: false,
voicemail: false,
},
direction: 'INBOUND',
}];
// prepare a `requirements` map which ...
// - on one hand maps `query`-syntax to a list items's structure
// - and on the other hand does so by providing an item specific
// filter condition/function for each necessary query endpoint.
const requirements = {
channels: {
texts: item => item.channel === 'SMS',
},
calls: {
voicemail: item => item.channel === 'VOICE' && !!item.callDetails.voicemail,
missed: item => item.channel === 'VOICE' && !item.callDetails.answered,
},
}
// const query = {
// channels: 'calls,texts',
// calls: 'voicemail,missed',
// };
function resolveQuery(requirements, query) {
const reject = item => false;
// create/collect a list of filter condition/functions
// which later will be applied as logical OR via `some`.
return Object
.entries(query)
.flatMap(([ groupKey, groupValue ]) =>
// e.g groupKey => 'channels',
// groupValue => 'calls,texts'
groupValue
.split(',')
.map(requirementKey =>
// e.g requirementKey => 'calls'
// or requirementKey => 'texts'
requirements?.[groupKey]?.[requirementKey?.trim()] ?? reject
)
);
}
function queryFromItemList(itemList, requirements, query) {
const conditionList = resolveQuery(requirements, query);
console.log(
'conditionList ... [\n ',
conditionList.join(',\n '),
'\n]'
);
return itemList.filter(item =>
conditionList.some(condition => condition(item))
);
}
console.log(
queryFromItemList(sampleList, requirements, {
channels: 'calls,texts',
calls: 'voicemail,missed',
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Remove parent object of a JSON if it has certain property

I'm getting a JSON structure from an API, that I want to change in my front end. The frontend adds a property to the JSON structure, "isHidden". When I send the modified JSON back, I don't want the object that has "isHidden" to be sent back to the API, but I will still save that internally in my own mongodb.
However, doing this was aperently a bit harder then I thought. I made this function wich works but I think is very ugly:
function removeHiddenObject(data,parent){
for(var property in data){
if(data.hasOwnProperty(property)){
if(property == "isHidden" && data[property] === true){
parent.splice(parent.indexOf(data), 1);
}
else {
if(typeof data[property] === "object") {
removeHiddenObject(data[property], data);
}
}
}
}
return data;
}
It's a recursive method, but I find it way to complex and weird. Is there a way of simplifying my task?
Here is a jsfiddle for you if you'd like to help out: https://jsfiddle.net/vn4vbne8/
use this code to remove it from json string :
myJson=s.replace(/,*\s*"[^"]"\s*\:\s*{(.*?)"isHidden"\:([^}]*)}/gm,"");
Be careful in Regex every character is important so use exactly above code.
It removes every property that have an object that one of its properties is isHidden.
Javascript actually supports non-enumerable public properties. I'm assuming that when you send data back to the server you first stringify it with JSON.stringify which will only stringify public enumerable properties of the object.
You can define a non-enumerable property like this (more on this here):
Object.defineProperty(obj, 'isHidden', {
enumerable: false,
writable: true
});
Where obj is the javascript object you want to add the property to and isHidden is the name of the property you are adding. When done this way, the new property is accessible as obj.isHidden but nevertheless will not show up in JSON.stringify output nor in for loops.
Here is a solution using object-scan. Takes a bit of time to wrap your head around it, but it helps with some heavy lifting around general data processing.
// const objectScan = require('object-scan');
const data = {"user":{"name":"Bob"},"buildingBlockTree":[{"uid":"a875ed6cf4052448f9e0cc9ff092a76d4","_id":"56a7353f682e1cc615f4a6ae","columns":[{"uid":"a0061fdd2259146bb84e5362eeb775186","_id":"56a7353f682e1cc615f4a6b1","buildingBlocks":[{"user":{"name":"lajdi"},"buildingBlockTree":[{"uid":"a875ed6cf4052448f9e0cc9ff092a76d4","_id":"56a7353f682e1cc615f4a6ae","columns":[{"uid":"a0061fdd2259146bb84e5362eeb775186","_id":"56a7353f682e1cc615f4a6b1","buildingBlocks":[]},{"uid":"abbcf3328854840deb96bb6b101df2b39","_id":"56a7353f682e1cc615f4a6af","buildingBlocks":[{"uid":"a931cf745d4b847ba9cdc7f4b830413be","_id":"56a7353f682e1cc615f4a6b0","source":{"limit":1,"itemsListId":1,"offset":0}}]}],"template":{"name":"Xs12Sm12Md6Lg12DotXs12Sm12Md6Lg12"}}],"_id":"56a7353f682e1cc615f4a6ad","source":{"limit":1,"itemsListId":1,"offset":0},"template":{"numberOfColumns":1},"uid":"a5f6a2fd1c80f49c0b97e0c7994400588"}]},{"uid":"abbcf3328854840deb96bb6b101df2b39","_id":"56a7353f682e1cc615f4a6af","buildingBlocks":[{"_id":"56a7353f682e1cc615f4a6b0","source":{"limit":1,"itemsListId":1,"offset":0},"isHidden":true}]}]}],"_id":"56a7353f682e1cc615f4a6ad","source":{"limit":1,"itemsListId":1,"offset":0},"uid":"a5f6a2fd1c80f49c0b97e0c7994400588","metadata":{"title":"sss"},"title":"sss","url":"sss"};
const removeHiddenObjects = (input) => objectScan(['**[*].isHidden'], {
rtn: 'count',
filterFn: ({ value, gparent, gproperty }) => {
if (value === true) {
gparent.splice(gproperty, 1);
return true;
}
return false;
}
})(input);
console.log(removeHiddenObjects(data)); // counts removals
// => 1
console.log(data);
/* => {
user: { name: 'Bob' },
buildingBlockTree: [ {
uid: 'a875ed6cf4052448f9e0cc9ff092a76d4',
_id: '56a7353f682e1cc615f4a6ae',
columns: [ {
uid: 'a0061fdd2259146bb84e5362eeb775186',
_id: '56a7353f682e1cc615f4a6b1',
buildingBlocks: [ {
user: { name: 'lajdi' },
buildingBlockTree: [ {
uid: 'a875ed6cf4052448f9e0cc9ff092a76d4', _id: '56a7353f682e1cc615f4a6ae', columns: [
{ uid: 'a0061fdd2259146bb84e5362eeb775186', _id: '56a7353f682e1cc615f4a6b1', buildingBlocks: [] },
{ uid: 'abbcf3328854840deb96bb6b101df2b39', _id: '56a7353f682e1cc615f4a6af', buildingBlocks: [
{ uid: 'a931cf745d4b847ba9cdc7f4b830413be', _id: '56a7353f682e1cc615f4a6b0', source: {
limit: 1,
itemsListId: 1,
offset: 0
} }
] }
],
template: { name: 'Xs12Sm12Md6Lg12DotXs12Sm12Md6Lg12' }
} ],
_id: '56a7353f682e1cc615f4a6ad',
source: { limit: 1, itemsListId: 1, offset: 0 },
template: { numberOfColumns: 1 },
uid: 'a5f6a2fd1c80f49c0b97e0c7994400588'
} ]
}, { uid: 'abbcf3328854840deb96bb6b101df2b39', _id: '56a7353f682e1cc615f4a6af', buildingBlocks: [] } ]
} ],
_id: '56a7353f682e1cc615f4a6ad',
source: { limit: 1, itemsListId: 1, offset: 0 },
uid: 'a5f6a2fd1c80f49c0b97e0c7994400588',
metadata: { title: 'sss' },
title: 'sss',
url: 'sss'
}
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#16.0.0"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources