Javascript sort object by key within nested objects - javascript

I have the following object:
{
4: {
1: [
{ order: 1, name: 'Test 4' }
]
},
0: {
15: [
{ order: 7, name: 'Test 1' },
{ order: 3, name: 'Test 3' },
],
12: {
{ order: 1, name: 'Test 2' }
}
}
}
Essentially what I am trying to achieve is to order this by the keys and then order further by the order property from within the nested value. So in turn I get the following output:
{
0: {
12: {
{ order: 1, name: 'Test 2' }
},
15: [
{ order: 3, name: 'Test 3' },
{ order: 7, name: 'Test 1' },
]
},
4: {
1: [
{ order: 1, name: 'Test 4' }
]
}
}
I then want to completely flatten this so it's without any of the outer object and just the data within the order, the outcome would then be:
[
{ name: 'Test 2' },
{ name: 'Test 3' },
{ name: 'Test 1' },
{ name: 'Test 4' }
]
I imagine this would be some kind of recursive operation which I need to do and I originally did it with something like the following but it got a bit messy:
Object.keys(obj)
.sort()
.reduce((acc, key) => { acc[key] = obj[key]; return acc; }, {});

Anotner one sorting approach
const obj = {4:{1:[{order:1,name:'Test 4'}]},0:{15:[{order:7,name:'Test 1'},{order:3,name:'Test 3'},],12:[{order:1,name:'Test 2'}]}};
const result = Object.entries(obj).flatMap(([u1, v1]) =>
Object.entries(v1).flatMap(([u2, v2]) =>
v2.map((v3) => ({ key: u1*1_000 + u2 + v3.order/1_000, item: v3 }))
)
)
.sort(({ key: a }, { key: b }) => a - b)
.map(({ item }) => item);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }

You can sort each obj by keys using Object.keys(obj).sort() and then access each element by its key.
Do this 2 times to get the array of object
const obj = {
4: {
1: [
{ order: 1, name: 'Test 4' }
]
},
0: {
15: [
{ order: 7, name: 'Test 1' },
{ order: 3, name: 'Test 3' },
],
12: [
{ order: 1, name: 'Test 2' }
]
}
}
let flatItems = []
const keys = Object.keys(obj).sort()
for (const key of keys){
const subObj = obj[key]
const subKeys = Object.keys(subObj).sort()
for(const subKey of subKeys){
flatItems = flatItems.concat(subObj[subKey].sort((a, b) => a.order - b.order))
}
}
console.log(flatItems)

The integer properties (in the range of 32 bit unsigned integers) don't need sorting, as iteration over them (e.g. via Object.values) is by specification already sorted by those integer keys. So the logic needs to focus only on sorting the inner objects, and it will be fine.
const flatSort = obj => Array.isArray(obj)
? [...obj].sort((a, b) => a.order - b.order).map(a => a.name)
: Object.values(obj).flatMap(flatSort);
const obj = { 4: { 1: [ { order: 1, name: 'Test 4' } ] }, 0: { 15: [ { order: 7, name: 'Test 1' }, { order: 3, name: 'Test 3' }, ], 12: [ { order: 1, name: 'Test 2' } ] } };
const res = flatSort(obj);
console.log(res);

Object keys can’t easily be sorted, the iteration order depends on different rules and isn’t straightforward to work with. As a result you’re better off converting your object into an array of key-value pair arrays (entries), and then sort that array rather than trying to sort your object (sorting is required as your object can have non-array index keys such as -1).
To do this, you can create a recursive function (sortEntries) that takes your object and grabs the entries from it. Using the key component of the entries, you can sort based on that. Once you've sorted the entries, you can .flatMap() the result of recursively sorting your nested object value by calling the sortEntries function again. For the base case (termination case), you can stop the recursion once you've found a value that is an array, which for that you can sort by the order property for your objects and then .map() each object to extract only the name property. Each array returned by .map() will be merged together into one resulting array due to the previous .flatMap() call:
const obj = { 4: { 1: [ { order: 1, name: 'Test 4' } ] }, 0: { 15: [ { order: 7, name: 'Test 1' }, { order: 3, name: 'Test 3' }, ], 12: [ { order: 1, name: 'Test 2' } ] } };
const sortEntries = (obj) => {
return Array.isArray(obj)
? obj.slice().sort((a, b) => a.order - b.order).map(({name}) => ({name}))
: Object.entries(obj).sort(([a], [b]) => a - b).flatMap(([, val]) => sortEntries(val));
}
const res = sortEntries(obj);
console.log(res);

Full Key/Value object sorting (array values included):
function sortKeys(object) {
if (Array.isArray(object))
return object.sort().map((obj) => (typeof obj === "object" ? sortKeys(obj) : obj));
const sortedObj = {};
const keys = Object.keys(object).sort();
for (var index in keys) {
const key = keys[index];
if (typeof object[key] === "object") {
sortedObj[key] = sortKeys(object[key]);
} else {
sortedObj[key] = object[key];
}
}
return sortedObj;
}

Related

Can we get an object from single object key value in javascript?

I have an array of object - like this -
test: [
{
id:'1',
name:'A'
},
{
id:'2',
name:'B'
},
]
Suppose I have a value 2 that exists in object Test as id. I want to get whole object from array if id value exists in whole array
input - 2,
expected output - {id:'2' , name:'B'}
How Can we get it ? is it any possible solution ?
Simply use find-
const val = [
{
id: '1',
name: 'A',
},
{
id: '2',
name: 'B',
},
];
const res = val.find(obj => obj.id === '2');
console.log(res);
There can be multiple ways to do this. Here is how I did it.
let test = [
{
id: '1',
name: 'A'
},
{
id: '2',
name: 'B'
}
];
let result = (param) => test.filter(el => {
return el.id == param
});
console.log(result(2))

How to convert array to object by key?

Suppose I got this array:
const users =[
{
id:1,
name:'bob',
},
{
id:2,
name:'sally',
},
{
id:3,
name:'bob',
age:30,
}
];
And I want to use any key(in this case 'name' ) to return an object :
{
bob:[
{
id:1,
name:'bob',
},
{
id:3,
name:'bob',
age:30,
}
],
sally:[
{
id:2,
name:'sally',
}
],
}
I tried this:
const go = (A,key) =>{
return A.reduce((o, key) => ({ ...o, [key]:o }), {})
}
export default go;
But this returns:
{ '[object Object]': { '[object Object]': { '[object Object]': {} } } }
If the key is not present omit from the result. It should not mutate the original array though. How can I perform this kind of conversion?
With the approach you have, a new array is not instantiated in case the key is not yet present in the object.
This will work:
const result = users.reduce((a, v) => {
a[v.name] = a[v.name] || [];
a[v.name].push(v);
return a;
}, {});
Complete snippet wrapping this logic in a function:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const go = (input, key) => input.reduce((a, v) => {
a[v[key]] = a[v[key]] || [];
a[v[key]].push(v);
return a;
}, {});
console.log(go(users, 'name'));
If you really want to cram it into a one-liner, this will also work, by either spreading the already existing array, or an empty one:
const result = users.reduce((a, v) => ({...a, [v.name]: [...a[v.name] || [], v]}), {});
Complete snippet wrapping this logic in a function:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const go = (input, key) => input.reduce((a, v) => ({...a, [v[key]]: [...a[v[key]] || [], v]}), {});
console.log(go(users, 'name'));
You were close but the key attribute in this case was each value (eg: { id: 1, name: 'bob' }) so the string representation is [object Object] which is why all the keys are that. Based off what you said, you want to use key.name as the property and set it's value as [key]. (I renamed key to arr in my example since it's the array value).
So this would be something like { ...o, [arr.name]: [arr] }
Because there can be an existing value, it adds a bit of complexity which is what [...(obj[arr.name] || []), arr] is doing. It's looking up the existing value (or defaulting to an empty array) and spreading those values and adding the new value.
const users = [{
id: 1,
name: 'bob',
},
{
id: 2,
name: 'sally',
},
{
id: 3,
name: 'bob',
age: 30,
}
];
const transform = (input, keyName) => {
return input.reduce((obj, arr) => ({ ...obj,
[arr[keyName]]: [...(obj[arr[keyName]] || []), arr]
}), {})
}
console.log(transform(users, 'name'))
console.log(transform(users, 'id'))

how to calculate a sum of an array in an object

I had a variable like that
const data = {
code: 1,
items: [
{ nickname: 1, name: [
{id : "A"},
{id : "B"}
]
},
{
nickname: 2, name: [
{id: "A"},
{id: "C"}
]
}
]
}
after that, I want to show how many characters: A:2, B:1, C:1
You can do that is following steps:
Use flatMap() on the array data.items
Inside flatMap() use map() to convert all the object to their id and return it from flatMap(). This way you will array ["A","B","A","C"]
Then use reduce() and get an object with count of all the letters.
const data = { code: 1, items: [ { nickname: 1, name: [ {id : "A"}, {id : "B"} ] }, { nickname: 2, name: [ {id: "A"}, {id: "C"} ] } ] }
const res = data.items.flatMap(x =>
x.name.map(a => a.id)
).reduce((ac,a) => (ac[a] = ac[a] + 1 || 1,ac),{});
console.log(res)
const data = {
code: 1,
items: [
{
nickname: 1,
name: [
{ id: "A" },
{ id: "B" }
]
},
{
nickname: 2,
name: [
{ id: "A" },
{ id: "C" }
]
}
]
};
const res = data.items.reduce((acc, next) => {
next.name.forEach(({ id }) => {
acc[id] = acc[id] + 1 || 1;
});
return acc;
}, {});
console.log(res);
You can do that in a single shot using reduce.
Reducing data.items will allow you to add to the accumulator (initially an empty object), the value of the currently looped name property item.
The result will be an object owning all the occurences of each encountered letter in the name property of each array.
Relevant lines explained:
data.items.reduce((acc, next) will call the reduce method on data.items. acc is the reduce accumulator (initially an empty object), next is the currently looped item of data.items.
next.name.forEach(({id}) in this line, we loop the name property of the currently looped item (data.items[n]). ({id}) is a short syntax to acquire the id property of the looped item in the foreach. It's equivalent to (item => item.id).
acc[id] = acc[id] + 1 || 1; tries to increase the property [id] of the accumulator (example: "A" of {}) by 1. If it does not exist, it sets the value to 1.
return acc; returns the accumulator.
You could iterate name and take id in a loop for assigning the count.
const
data = { code: 1, items: [{ nickname: 1, name: [{ id : "A" }, { id : "B" }] }, { nickname: 2, name: [{ id: "A" }, { id: "C" }] }] },
result = data.items.reduce(
(r, { name }) => (name.forEach(({ id }) => r[id] = (r[id] || 0 ) + 1), r),
{}
);
console.log(result);

Find all values by specific key in a deep nested object

How would I find all values by specific key in a deep nested object?
For example, if I have an object like this:
const myObj = {
id: 1,
children: [
{
id: 2,
children: [
{
id: 3
}
]
},
{
id: 4,
children: [
{
id: 5,
children: [
{
id: 6,
children: [
{
id: 7,
}
]
}
]
}
]
},
]
}
How would I get an array of all values throughout all nests of this obj by the key of id.
Note: children is a consistent name, and id's won't exist outside of a children object.
So from the obj, I would like to produce an array like this:
const idArray = [1, 2, 3, 4, 5, 6, 7]
This is a bit late but for anyone else finding this, here is a clean, generic recursive function:
function findAllByKey(obj, keyToFind) {
return Object.entries(obj)
.reduce((acc, [key, value]) => (key === keyToFind)
? acc.concat(value)
: (typeof value === 'object')
? acc.concat(findAllByKey(value, keyToFind))
: acc
, [])
}
// USAGE
findAllByKey(myObj, 'id')
You could make a recursive function like this:
idArray = []
function func(obj) {
idArray.push(obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
Snippet for your sample:
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
}
idArray = []
function func(obj) {
idArray.push(obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
func(myObj)
console.log(idArray)
I found steve's answer to be most suited for my needs in extrapolating this out and creating a general recursive function. That said, I encountered issues when dealing with nulls and undefined values, so I extended the condition to accommodate for this. This approach uses:
Array.reduce() - It uses an accumulator function which appends the value's onto the result array. It also splits each object into it's key:value pair which allows you to take the following steps:
Have you've found the key? If so, add it to the array;
If not, have I found an object with values? If so, the key is possibly within there. Keep digging by calling the function on this object and append the result onto the result array; and
Finally, if this is not an object, return the result array unchanged.
Hope it helps!
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
}
function findAllByKey(obj, keyToFind) {
return Object.entries(obj)
.reduce((acc, [key, value]) => (key === keyToFind)
? acc.concat(value)
: (typeof value === 'object' && value)
? acc.concat(findAllByKey(value, keyToFind))
: acc
, []) || [];
}
const ids = findAllByKey(myObj, 'id');
console.log(ids)
You can make a generic recursive function that works with any property and any object.
This uses Object.entries(), Object.keys(), Array.reduce(), Array.isArray(), Array.map() and Array.flat().
The stopping condition is when the object passed in is empty:
const myObj = {
id: 1,
anyProp: [{
id: 2,
thing: { a: 1, id: 10 },
children: [{ id: 3 }]
}, {
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{ id: 7 }]
}]
}]
}]
};
const getValues = prop => obj => {
if (!Object.keys(obj).length) { return []; }
return Object.entries(obj).reduce((acc, [key, val]) => {
if (key === prop) {
acc.push(val);
} else {
acc.push(Array.isArray(val) ? val.map(getIds).flat() : getIds(val));
}
return acc.flat();
}, []);
}
const getIds = getValues('id');
console.log(getIds(myObj));
Note: children is a consistent name, and id's wont exist outside
of a children object.
So from the obj, I would like to produce an array like this:
const idArray = [1, 2, 3, 4, 5, 6, 7]
Given that the question does not contain any restrictions on how the output is derived from the input and that the input is consistent, where the value of property "id" is a digit and id property is defined only within "children" property, save for case of the first "id" in the object, the input JavaScript plain object can be converted to a JSON string using JSON.stringify(), RegExp /"id":\d+/g matches the "id" property and one or more digit characters following the property name, which is then mapped to .match() the digit portion of the previous match using Regexp \d+ and convert the array value to a JavaScript number using addition operator +
const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};
let res = JSON.stringify(myObject).match(/"id":\d+/g).map(m => +m.match(/\d+/));
console.log(res);
JSON.stringify() replacer function can alternatively be used to .push() the value of every "id" property name within the object to an array
const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};
const getPropValues = (o, prop) =>
(res => (JSON.stringify(o, (key, value) =>
(key === prop && res.push(value), value)), res))([]);
let res = getPropValues(myObject, "id");
console.log(res);
Since the property values of the input to be matched are digits, all the JavaScript object can be converted to a string and RegExp \D can be used to replace all characters that are not digits, spread resulting string to array, and .map() digits to JavaScript numbers
let res = [...JSON.stringify(myObj).replace(/\D/g,"")].map(Number)
Using recursion.
const myObj = { id: 1, children: [ { id: 2, children: [ { id: 3 } ] }, { id: 4, children: [ { id: 5, children: [ { id: 6, children: [ { id: 7, } ] } ] } ] }, ]},
loop = (array, key, obj) => {
if (!obj.children) return;
obj.children.forEach(c => {
if (c[key]) array.push(c[key]); // is not present, skip!
loop(array, key, c);
});
},
arr = myObj["id"] ? [myObj["id"]] : [];
loop(arr, "id", myObj);
console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can make a recursive function with Object.entries like so:
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
};
function findIds(obj) {
const entries = Object.entries(obj);
let result = entries.map(e => {
if (e[0] == "children") {
return e[1].map(child => findIds(child));
} else {
return e[1];
}
});
function flatten(arr, flat = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, flat);
} else {
flat.push(value);
}
}
return flat;
}
return flatten(result);
}
var ids = findIds(myObj);
console.log(ids);
Flattening function from this answer
ES5 syntax:
var myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
};
function findIds(obj) {
const entries = Object.entries(obj);
let result = entries.map(function(e) {
if (e[0] == "children") {
return e[1].map(function(child) {
return findIds(child)
});
} else {
return e[1];
}
});
function flatten(arr, flat = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, flat);
} else {
flat.push(value);
}
}
return flat;
}
return flatten(result);
}
var ids = findIds(myObj);
console.log(ids);
let str = JSON.stringify(myObj);
let array = str.match(/\d+/g).map(v => v * 1);
console.log(array); // [1, 2, 3, 4, 5, 6, 7]
We use object-scan for a lot of our data processing needs now. It makes the code much more maintainable, but does take a moment to wrap your head around. Here is how you could use it to answer your question
// const objectScan = require('object-scan');
const find = (data, needle) => objectScan([needle], { rtn: 'value' })(data);
const myObj = { id: 1, children: [{ id: 2, children: [ { id: 3 } ] }, { id: 4, children: [ { id: 5, children: [ { id: 6, children: [ { id: 7 } ] } ] } ] }] };
console.log(find(myObj, '**.id'));
// => [ 7, 6, 5, 4, 3, 2, 1 ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan
import {flattenDeep} from 'lodash';
/**
* Extracts all values from an object (also nested objects)
* into a single array
*
* #param obj
* #returns
*
* #example
* const test = {
* alpha: 'foo',
* beta: {
* gamma: 'bar',
* lambda: 'baz'
* }
* }
*
* objectFlatten(test) // ['foo', 'bar', 'baz']
*/
export function objectFlatten(obj: {}) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(objectFlatten(value));
} else {
result.push(value);
}
}
return flattenDeep(result);
}
Below solution is generic which will return all values by matching nested keys as well e.g for below json object
{
"a":1,
"b":{
"a":{
"a":"red"
}
},
"c":{
"d":2
}
}
to find all values matching key "a" output should be return
[1,{a:"red"},"red"]
const findkey = (obj, key) => {
let arr = [];
if (isPrimitive(obj)) return obj;
for (let [k, val] of Object.entries(obj)) {
if (k === key) arr.push(val);
if (!isPrimitive(val)) arr = [...arr, ...findkey(val, key)];
}
return arr;
};
const isPrimitive = (val) => {
return val !== Object(val);
};

How do I recursively search an object tree and return the matching object based on a key/value using JavaScript/Prototype 1.7

I've got some nested object data and I want to search it and return the matching object based on the id.
var data = [{id: 0, name: 'Template 0', subComponents:[
{id: 1, name: 'Template 1', subItems:[
{id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
]}
]}
];
So I want to do something like this
getObjectByKeyValue({id: 3})
and have it return
{id: 3, name: 'Template 3'}
It's sort of got to be done generically because I have subItems, AND subComponents which could each have children.
I tried this using Prototype 1.7 and no luck - I think this just searches an array, and not a tree with it's sub nodes:
data.find(function(s){return s.id == 4;})
Thanks in advance!!!!!!
I went a slightly different route and made the findKey method an Object protype:
Object.prototype.findKey = function(keyObj) {
var p, key, val, tRet;
for (p in keyObj) {
if (keyObj.hasOwnProperty(p)) {
key = p;
val = keyObj[p];
}
}
for (p in this) {
if (p == key) {
if (this[p] == val) {
return this;
}
} else if (this[p] instanceof Object) {
if (this.hasOwnProperty(p)) {
tRet = this[p].findKey(keyObj);
if (tRet) { return tRet; }
}
}
}
return false;
};
Which you would call directly on the data object, passing in the key/value you're looking for:
data.findKey({ id: 3 });
Note that this function allows you to find an object based on any key:
data.findKey({ name: 'Template 0' });
See example → (open console to view result)
Not the best of the and final solution.
But can get you a start for what you are looking...
var data = [{id: 0, name: 'Template 0', subComponents:[
{id: 1, name: 'Template 1', subItems:[
{id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
]}
]}
];
function returnObject(data,key,parent){
for(var v in data){
var d = data[v];
if(d==key){
return parent[0];
}
if(d instanceof Object){
return returnObject(d,key,data);
};
}
}
function returnObjectWrapper(datavar,key){
return returnObject(datavar,key.id)
}
returnObjectWrapper(data,{id:3})
Please see my solution below or http://jsfiddle.net/8Y6zq/:
var findByKey = function (obj, key) {
var j, key = key || '', obj = obj || {}, keys = key.split("."),
sObj = [], ssObj = [], isSelector = !!(keys.length > 0);
var findKey = function (obj, key) {
var k;
for (k in obj) {
if (k === key) {
sObj.push(obj[k]);
} else if (typeof obj[k] == 'object') {
findKey(obj[k], key);
}
}
};
if (isSelector) {
var nKey = keys.shift();
findKey(obj, nKey);
while (keys.length > 0) {
nKey = keys.shift();
if (sObj.length > 0) {
ssObj = sObj.slice(0), sObj = [];
for (j in ssObj) {
findKey(ssObj[j], nKey);
}
}
}
} else {
findKey(obj, key);
}
// return occurrences of key in array
return (sObj.length === 1) ? sObj.pop() : sObj;
};
var data = [
{id: 0, name: 'Template 0', subComponents: [
{id: 1, name: 'Template 1', subItems: [
{id: 2, name: 'Template 2', subComponents: [
{id: 3, name: 'Template 3'}
], subItems: [
{id: 4, name: 'Template 4'}
]}
]}
]},
{subComponents:{
comp1:'comp1 value',
comp2:'comp2 value',
}}
];
alert(JSON.stringify(findByKey(data, 'subComponents')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp1')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp2')));
In this implementation we can use search by KEY or SELECTOR (eg. "<paren_key>.<child_key_1>.<child_key_2>. ... <child_key_N>")
In case you really need a search through your tree data return all results (not a unique key), here is a little modified version of mVChr's answer:
Object.prototype.findKey = function (keyObj) {
var p, key, val, tRet;
var arr = [];
for (p in keyObj) {
if (keyObj.hasOwnProperty(p)) {
key = p;
val = keyObj[p];
}
}
for (p in this) {
if (p == key) {
if (this[p] == val) {
arr.push(this);
}
} else if (this[p] instanceof Object) {
if (this.hasOwnProperty(p)) {
tRet = this[p].findKey(keyObj);
if (tRet) {
for (var i = 0; i < tRet.length; i++)
arr.push(tRet[i]);
}
}
}
}
if (arr.length > 0)
return arr;
else
return false;
};
We now use object-scan for data processing tasks like this. It's pretty powerful once you wrap your head around how to use it. Here is how you'd answer your questions
// const objectScan = require('object-scan');
const find = (id, input) => objectScan(['**'], {
abort: true,
rtn: 'value',
filterFn: ({ value }) => value.id === id
})(input);
const data = [{ id: 0, name: 'Template 0', subComponents: [{ id: 1, name: 'Template 1', subItems: [{ id: 2, name: 'Template 2', subComponents: [{ id: 3, name: 'Template 3' }], subItems: [{ id: 4, name: 'Template 4' }] }] }] }];
console.log(find(3, data));
// => { id: 3, name: 'Template 3' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.8.0"></script>
Disclaimer: I'm the author of object-scan

Categories