Why does '.includes' work on an object inside a looped array? - javascript

I was hoping someone could help me understand something about the '.includes' method.
My understanding was that this only worked on arrays? for e.g. myarray.includes('something').
But it also seems to work when you loop over the array and use it on an object for e.g:
var people = [
{
name: 'Joe',
age: 27
},
{
name: 'Rob',
age: 25
},
{
name: 'Dave',
age: 22
}
];
for(i=0; i<people.length; i++) {
console.log(people[i].name.includes('Joe')) // True
}
Can someone explain why this is?
Thanks,
Joe

Because name is of type string, which also has an includes method. You can read on that here.

Related

How to relate two (or more) objects through a property (in javascript)?

Let's say I have these two objects:
let person1 = {name: "Charlie", age: 65, childrenNames:["Ruth", "Charlie Jr."] parentNames: ["Dolph", "Grace"]};
let person2 = {name: "Charlie Jr.", age: 34, childrenNames:[] parentNames: ["Charlie", "Grace"]};
Now let's say I want to express the fact that person1 is person2's father and, consequently, that person2 is person1's son. That is, the "Charlie Jr" in the person1's childrenNames property is person2 and the "Charlie" in the person2's parentNames property is person1.
How could I achieve this? I don't see how embedding one object inside the other would solve the problem, but simply replicate it. Is there a way to make a property inside an object a sort of identifier for another object?
Thanks so much!
For example if you want to know if someone is the child of person 1, you can do something like this:
person1.childrenNames.forEach((childrenName) => {
if(childrenName=== person2.name) {
console.log(person1.name + ' is the parent of + person2.name);
});
Also you can do a nested function so you can check if the person if the parent of multiple persons.
Why not add relationship indexes ? combine your people, to 1 people array.
Iterate and add instead of parentNames, parentIndexes. This way, instead of looking for parents or sons by names, you have the index.
Note, to make my example simple, I am only doing parent to son relationship. You can easily add a son to parent relationship using the exact same logic.
Example
if (peopleArray[i].parentsIndex.length > 0) {
// get first parent
//peopleArray[peopleArray[i].parentsIndex[0]];
}
Modify your object.
let peopleArray = [
{
name: "Charlie",
age: 65,
parentNames: ["Dolph", "Grace"]
},
{
name: "Grace",
age: 65,
parentNames: ["Dolph", "Grace"]
},
{
name: "Dolph",
age: 65,
parentNames: ["ADSGS", "Grace"]
}
];
peopleArray = peopleArray.map(callback.bind(null));
function callback(item) {
item["parentsIndex"] = [];
for (let i = 0; i < item.parentNames.length; i++) {
let parentObj = peopleArray.find(x => x.name === item.parentNames[i]);
if (parentObj !== undefined) {
item["parentsIndex"].push(peopleArray.indexOf(parentObj));
}
}
return item;
}
console.log(peopleArray);
// use case
if (peopleArray[0].parentsIndex.length > 0) {
// get first parent
//peopleArray[peopleArray[0].parentsIndex[0]];
}
I guess it depends on how complicated your scenario would be and what you would like to achieve, but say you add an extra table for relations. This table could hold information on the type of relation 2 persons share, and could then be used to look up that data.
For example, if we have 4 persons, from which 2 are parents (Charlie & Grace) and 1 is the son (Charlie Jr), we could form a relation table as below.
We don't need to indicate that Charlie Jr is a son, as he we already know the parents of the child.
const familyDb = {
persons: [
{ id: 1, name: 'Charlie', age: 68 },
{ id: 2, name: 'Grace', age: 64 },
{ id: 3, name: 'Charlie Jr', age: 34 },
{ id: 4, name: 'Grace', age: 36 }
],
relations: [
{ id: 1, person1: 1, person2: 2, type: 'spouse', from: 1970, till: null },
{ id: 2, person1: 3, person2: 4, type: 'spouse', from: 2010, till: null },
{ id: 3, person1: 1, person2: 3, type: 'parent' },
{ id: 3, person1: 2, person2: 3, type: 'parent' }
]
};
function getParents( person ) {
return familyDb.relations.filter( relation => relation.person2 === person.id && relation.type === 'parent' );
}
function getChildren( person ) {
return familyDb.relations.filter( relation => relation.person1 === person.id && relation.type === 'parent' );
}
console.log( getParents( familyDb.persons[2] ) );
console.log( getChildren( familyDb.persons[0] ) );
So the above code kinda takes a rudimentary approach to this, you have:
a unique id identifying a person (name matching would be hard in your example as Grace is both the mom of Charlie & Charlie Jr)
a table identifying a relation of some type between two persons
After that you just need a way to look up the information from your dataset and you have a way to get started

Accessing infinite nested children object

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.

Writing a JSON file a string

could someone give me some direction on how to write a piece of JSON text in JavaScript. eg
{
"Header.MainsiteURL": "http://www.ford.es",
"Header.backToMainsiteMobile": "ES-Main site"
}
You can declare a single Json object using the following syntax.
var person = {
Name: "NameOfPerson",
Age: 23
}
The following is a Json array for storing people's names and age.
var people = [
{
Name: "NameOfPerson",
Age: 23
},{
Name: "NameOfAnotherPerson",
Age: 12
}
]
What you seem to be missing in your example are the properties of the object.

Ramda JS: How to perform a map where I call R.replace for a given property on each object?

Given the following data:
const my_data = [
{
name: "John",
age: 22
},
{
name: "Johnny",
age: 15
},
{
name: "Dave",
age: 27
}
]
I want to transform the data such that the substring "John" is replaced with "Ben" in each of the name properties so it looks like this:
[
{
name: "Ben",
age: 22
},
{
name: "Benny",
age: 15
},
{
name: "Dave",
age: 27
}
]
I want to do so in the proper functional way (I think is points-free but I am still learning), so I can reuse this in a pipeline, say first reducing by age and then doing the replace, or doing the replace first then doing a sort. How would I do this using the Ramda functions?
var fix_names = ???
var fixed_data = R.map( fix_names, my_data );
R.map(R.over(R.lensProp('name'), R.replace('John', 'Ben')))(my_data)
See R.over and R.lensProp.
There's no reason to prefer point-free functions. Readability is what really matters:
var myData = [ new Person("John", 22)
, new Person("Johnny", 15)
, new Person("Dave", 27)
];
var fixedData = myData.map(fixName);
alert(JSON.stringify(fixedData, null, 4));
function fixName(person) {
return Object.assign(new Person, person, {
name: person.name.replace(/John/g, "Ben")
});
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Point-free functions are useful in very limited cases like eta conversion and function composition. Point-free functions should not be treated as the cornerstone of functional programming.

Property undefined halfway through Javascript array

I'm trying to compare each object in the two arrays in order to find matches. Currently, I am only comparing one property, but plan to compare two properties when I can get this part working.
I find it odd that it works for the first three items in the array and returns an error on the fourth. Here is the console output in Chrome:
Washington
Smith
yes
Jones
Uncaught TypeError: Cannot read property 'name' of undefined
Here is my javascript:
var self = this;
self.people = [
{ id: '1', name: 'Washington' },
{ id: '2', name: 'Smith' },
{ id: '1', name: 'Jones' },
{ id: '1', name: 'Smith' },
{ id: '3', name: 'Washington' }
];
self.params = [
{id: '1', name: 'Jones'},
{id: '2', name: 'Smith'}];
for (var value in self.params) {
for (var value in self.people) {
console.log(self.people[value].name);
if (self.people[value].name == self.params[value].name) {
console.log('yes');
}
}
}
If I remove the if statement, the code runs without error and prints the "names" in the people array twice as expected. Thoughts? Thanks in advance!
You're using twice the variable name "value".
Btw in Javascript the variables aren't scoped at block level (your 2 var declarations in the 2 for), but they're either global or function scoped.
I'm not sure what exactly you want to achieve, but maybe the next lines can give you a hint:
var val,
value;
for (val in self.params) {
for (value in self.people) {
console.log(self.people[value].name);
if (self.people[value].name == self.params[val].name) {
console.log('yes');
}
}
}
for (var value in self.params) {
for (var value1 in self.people) {
console.log(self.people[value1].name);
if (self.people[value1].name == self.params[value].name) {
console.log('yes');
}
}
}
You are using the same variable for both the loops...

Categories

Resources