Accessing infinite nested children object - javascript

Wanted to know how can we access infinitely nested object in JS?
Consider this example given to be my interviewer
You have an object with a Parent and infinitely nested children
[
{
name: "Jack",
age: "98" ,
profession: "doctor
children: [
{
name: "Varun",
age: "80"
profession: "scientist"
children: [
{
name: "Ishan"
age: "62",
profession: "teacher
children: [{....
.....
.....[{
name: "Rahul",
age: "23",
profession: "engineer"
children: [{
.....
I need to find the name corresponding where profession is "engineer" and how deep that given object is nested.
Note: Number of children to be considered here is infinite.
Question: Can someone help me in figuring out how I can do it with recursion and without recursion
update: He gave me a hint to use divide and conquer
Update: Based on the solution by Bary, I tried something like this
let infiniteArray = [
{
name: "Jack",
age: "98" ,
profession: "doctor",
children: [
{
name: "Varun",
age: "80",
profession: "scientist",
children: [
{
name: "Ishan",
age: "62",
profession: "teacher"
}
]
}
]
}
]
function isTheItem(item) {
if (item["profession"] === "teacher") return item
return false
}
function walk(collection) {
return collection.find(item => isTheItem(item) || walk(item.children));
}
But when I console.log it, i.e console.log(walk(infiniteArray)), it is logging the entire infiniteArray and I understand why but I went it to return just the name corresponding to profession. Any help on how I can achieve it?
name: "Ishan",
age: "62",
profession: "teacher"
}

There's two directions walking through your collection
* sibling
* nested
so you can iterate this sibling items with regular array iterator and recursively walk through the children of each item.
function isTheItem(item) {
return ...;
}
function walk(collection) {
return collection.find(item => isTheItem(item) || walk(item.children));
}

Divide and conquer algorithms usually have more to do with sorting values in an array (during an interview process). If you were sorting by age or something, I could see that being a hint. But there's no way to really divide and conquer when searching for a key value pair of an infinite number of nested objects. You have to search through n number of values until you find the result. Any dividing of the object doesn't necessarily improve efficiency with a random key value pair stored that you want to find.
More experienced devs correct me if I'm wrong here
Barry Gane has a good start to the code you would write for the actual application of this.

Related

How do I compare an object property values to the values of an array, and then replace the object values with the array values?

Let's say I have an array like this one (i'm adding random letters just to recreate my example a little better).
arr1 = ["appless", "bananarr", "orangeaa", "coconutvv", "pineapplevv"]
Then I have a group of objects.
const objects: [{
name: "john",
job: "carpenter",
color: "blue"
status: "banana"},
{
name: "john",
job: "plumber",
favorites: "banana", "apple", "orange",
color: "blue", "purple"},
{
name: "john",
job: "carpenter",
favorites: "orange", "pineapple",
gender: "female"}]
As you can see my objects have different properties, but a lot of values match one or more values in my arr1.
Now, for every value that mostly matches one of the strings in my arr1, I want to replace index of the matched value in arr1 into the object value (like shown below), for every object and for every property.
Example result:
const objects: [{
name: "john",
job: "carpenter",
color: "blue"
status: 1},
{
name: "john",
job: "plumber",
favorites: 1, 0, 2,
color: "blue", "purple"},
{
name: "john",
job: "carpenter",
gender: "female", 2}]
What I'm actually trying to do in reality is to dynamically replace string values of libraries/technologies/frameworks/etc (i.e. "React") from a portfolio project (the objects are fetched from a local json) with their respective icons (for that I'm using React icons). I don't want to go edit the json directly.
I put all the icon components that I need in an array, then I used that to make a copy array with the "string" values of those icon components (array.map).
To get the index: I THINK it's best to try and match arr1 one by one ("favorites", "status", and "gender" in this example), something like
objects.map(object=>{object.favorites.includes("orangeaa").indexOf()} ??
Not all objects have a "favorites" property, so from that i will get some undefined results...
Once I manage to get that index number, I will use it to render the actual icon.
Since I'm using react, it will be something like this:
{object.favorites && (<div>
<h3>Favs:</h3>{object.favorites.map(i=><p key={i}>{iconComponentsArray[i]}</p>)}
You could map the favorites with the indices of the target array.
function getIndices(values, targets) {
return values.map(s => targets.findIndex(t => t.includes(s)));
}
console.log(getIndices(
["banana", "apple", "orange"],
["appless", "bananarr", "orangeaa", "coconutvv", "pineapplevv"]
));

Check if an array of object is exactly equal to another array that contains one of its property [duplicate]

This question already has answers here:
Check if an array contains any element of another array in JavaScript
(32 answers)
Closed 1 year ago.
I have these 2 arrays
The first one is fixed and does not change and contains the id of the 2nd array:
fixed=["123","456","789"]
The second can change
variableArray=[{name:"Joe",id:"123"},{name:"Joe",id:"456"},{name:"Joe",id:"789"}]
I want to return true if, even if there were some changes at the end the variable array is the same length and contains exactly the same keys of the "fixed"
NOT VALID:
fixed=["123","456","789"]
variableArray=[{name:"Joe",id:"456"},{name:"Joe",id:"789"}]
return false because is missing the id "123" (and the length is also different so is excluded by default)
NOT VALID:
fixed=["123","456","789"]
variableArray=[{name:"Joe",id:"123"},{name:"Joe",id:"456"},{name:"Joe",id:"001"}]
this will return false because, even if contains 3 elements as there are in the "fixed" is missing the id "789" and have another "001" instead
as #mplungjan mentiond, you can use Every:
let fixed = ["123", "456", "789"];
let variableArray1 = [{
name: "Joe",
id: "123"
}, {
name: "Joe",
id: "456"
}, {
name: "Joe",
id: "789"
}];
let variableArray2 = [{
name: "Joe",
id: "123"
}, {
name: "Joe",
id: "456"
}, {
name: "Joe",
id: "001"
}]
let containsAll1 = variableArray1.every(elem => fixed.includes(elem.id));
let containsAll2 = variableArray2.every(elem => fixed.includes(elem.id));
console.log(containsAll1, containsAll2);

Javascript - Access nested elements of JSON object

So I have a series of 4 JSON objects with nested data inside each of them. Each of these objects are stored in an array called classes. Here is an example of how one of the class objects is formatted:
let class_A = {
professor: "Joey Smith",
numberStudents: 25,
courseCode: "COMS 2360",
seating: {
"FirstRow": {
0: {
firstName: "Sarah",
collegeMajor: "English",
},
1: {
firstName: "Bob",
collegeMajor: "Computer Engineering",
},
2: {
firstName: "Dylan",
collegeMajor: "Mathematics",
}
},
"SecondRow": {
3: {
firstName: "Molly",
collegeMajor: "Music"
}
}
}
};
I'm struggling to figure out how to access the very last fields within each class object (firstName and collegeMajor). The furthest I was able to get was the indexes beneath each row number.
let classes = [class_A, class_B, class_C, class_D];
let classesAvailable = document.getElementById('classes');
let class = classes[classesAvailable.value];
for(rowNum in class.seating){
for(index in class.seating[rowNum]){
console.log(index);
//console.log(class.seating[rowNum[index]].firstName);
}
}
So in this example, console.log(index) prints out:
0
1
2
3
but I'm unable to print the first name and college major of each student in each row. I was trying to follow a similar logic and do console.log(class.seating[rowNum[index]].firstName) but I get the error:
Cannot read properties of undefined (reading 'firstName')
Was wondering if anyone knows what's wrong with my logic here?
console.log(class.seating[rowNum][index])

Nested arrays with objects, lodash meanBy

Can someone please help me understand how to make this work. Everytime I feel like I start to understand arrays and objects in Javascript it turns out that I still don't.
I'm trying to get the average of all prices in the following datastructure by using lodash meanBy
[
{
date: "2019-12-17",
items: [
{ id: "1", state: "accepted", price: "90.5" },
{ id: "2", state: "rejected", price: "20.0" },
{ id: "3", state: "open", price: "10.5" },
]
},
{
date: "2019-12-18",
items: [
{ id: "4", state: "open", price: "450.0" },
{ id: "5", state: "rejected", price: "40.1" },
{ id: "6", state: "accepted", price: "50.9" },
]
}
]
If you provide the answer, can you also please try to explain how you select something nested in items, because that's as far as I get before I get lost.
In this case instead of selecting nested values, it's easier to flatten the items to a single array, and then apply _.meanBy(). In addition, the prices are strings, and not numbers, so you'll need to convert them.
Flatten the items to a single array with Array.flatMap(), and then use _.meanBy(), and get the numeric values of the prices:
const data = [{"date":"2019-12-17","items":[{"id":"1","state":"accepted","price":"90.5"},{"id":"2","state":"rejected","price":"20.0"},{"id":"3","state":"open","price":"10.5"}]},{"date":"2019-12-18","items":[{"id":"4","state":"open","price":"450.0"},{"id":"5","state":"rejected","price":"40.1"},{"id":"6","state":"accepted","price":"50.9"}]}]
const result = _.meanBy(_.flatMap(data, 'items'), o => +o.price)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Another approach is to get the general average, by getting the average of each items array separately , and then getting the average of all averages.
const data = [{"date":"2019-12-17","items":[{"id":"1","state":"accepted","price":"90.5"},{"id":"2","state":"rejected","price":"20.0"},{"id":"3","state":"open","price":"10.5"}]},{"date":"2019-12-18","items":[{"id":"4","state":"open","price":"450.0"},{"id":"5","state":"rejected","price":"40.1"},{"id":"6","state":"accepted","price":"50.9"}]}]
const result = _.meanBy(data, ({ items }) => _.meanBy(items, o => +o.price))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Copy without keeping reference [duplicate]

This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 4 years ago.
So I have a variable called elements that hold a bunch of data. Let's say, for example, that this is it:
{
name: "Jeff",
age: "18",
carList: [
"car1": "...",
"car2": "..."
],
surname: "Matt"
}
I also have an empty array, at the start, declared this way:
public myArray: Model[] = [];
Model is just a class that contains the definition of the elements.
What I'm trying to achive is to have a copy of elements without keeping any reference to the original variable. but I'm missing something. Here's a pseudo-code that do the trick (almost) :
myfunction(){
//Do stuff that change `car1` from `...` to `hello`
myArray.push(Object.assign({}, this.elements));
}
And finnally a I have a function that print everything in the myArray variable:
function print(){
this.myArray.forEach(el => {
console.log(el);
});
}
The problem is that every element of the array has the latest update done by me.
So if myFunction was called several time doing something like:
Change "Jeff" to "Jack"
Change age "18" to "25"
Change surname to "Seth"
what I see is three log showing this data:
{
name: "Jeff",
age: "25",
carList: [
"car1": "...",
"car2": "..."
],
surname: "Seth"
}
My question is: Why even using Object.asign it still keeping the reference to it's original object? I should keep the history of each modification, instead of having just the last edit in both of three edits I've made.
Thank you.
Try the following:
JSON.parse(JSON.stringify(element));
It keeps no refrences, as you can observe in the snippet below:
let element = { name: "Jeff", age: "18", carList: [ {"car1": "x"}, {"car2": "y"} ], surname: "Matt" };
let result = JSON.parse(JSON.stringify(element));
result.name = "x";
console.log(result);
console.log("****element*****");
console.log(element);

Categories

Resources