Functional Programming exercise I can't figure out - javascript

I've been looking at a problem for hours and failing to find a solution. I'm given an array of customer objects.
In each customer object is an array of friends.
In the array of friends is an object for each friend, containing some data, including a name key/value pair.
What I'm trying to solve for: I'm given this customers array and a customer's name. I need to create a function to find if this customer name is in any other customer's friend lists, and if so, return an array of those customer's names.
Below is a customer list. And as an example, one of the customers is Olga Newton. What the code should be doing is seeing that Olga Newton is a customer and is also in the friends lists of Regina and Jay, and should be returning an array of Regina and Jay.
I thought I could do this simply with a filter function, but because the friends list is an array with more objects, this is adding level of complexity for me I can't figure out.
Below is a customer array. The out put should be
['Regina', 'Jay']
and what I've gotten has either been
[{fullCustomerObj1}, {fullCustomerObj2}]
or
[ ]
What am I missing?
Here is the customer array:
var customers = [{
name: "Olga Newton",
age: 43,
balance: "$3,400",
friends: [{
id: 0,
name: "Justice Lara"
}, {
id: 1,
name: "Duke Patrick"
}, {
id: 2,
name: "Herring Hull"
}, {
id: 3,
name: "Johnnie Berg"
}]
}, {
name: "Regina",
age: 53,
balance: "$4,000",
friends: [{
id: 0,
name: "Cheryl Kent"
}, {
id: 1,
name: "Cynthia Wells"
}, {
id: 2,
name: "Gutierrez Waters"
}, {
id: 3,
name: "Olga Newton"
}]
}, {
name: "Jay",
age: 28,
balance: "$3,000",
friends: [{
id: 0,
name: "Cross Barnett"
}, {
id: 1,
name: "Raquel Haney"
}, {
id: 2,
name: "Olga Newton"
}, {
id: 3,
name: "Shelly Walton"
}]
}];

Use filter and map, please.
function friends(c, name){
return c.filter((a) => {
return a.friends.map(b => b.name).includes(name)
}).map(a => a.name);
}
console.log(friends(customers, "Olga Newton"));
// ['Regina', 'Jay']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

We look to an array (friends[]) inside anther (customers[]), So used two for loops, the first determine witch customer will look for his friends, and the second the array will search inside, then set if statement if the cust name is inside friends[]: adding the customer name to customerFriends[] array, At the end return the customerFriends[].
let cust = "Olga Newton"; // Get the customer name who you look for his friends.
const findFriend = (cust, arrs) => { // Create findFriend function.
let customerFriends = []; // Create an array to set the result to it.
for (let i = 0; i < arrs.length; i++) { // For each Customer.
for (const arr of arrs[i].friends) { // For each Friend.
if (arr.name === cust) { // Use Strict equality to find Customer name in friends[].
customerFriends.push(arrs[i].name); // Add the customer name to the customerFriends[].
}
}
}
return customerFriends;// Return the final results.
}
console.log(findFriend(cust, customers)); // Call the function.

Related

transform an array of objects with map( )

I can't understand how the map () method works because all the examples are with numbers and to understand I need an example with something more specific.
so I made this
I have an array of objects:
let people = [
{
id: 1,
name: 'jhon',
last_name: 'wilson'
},
{
id: 2,
name: 'maria',
last_name: 'anyway'
},
{
id: 3,
name: 'lastOne',
last_name: 'example'
}
];
I want to understand how with people.map(); i can change the idk, name?? of the 2nd element.
this is how i think map() work:
people.map(() => {
people[1].name = prompt()
// At this point i don't know how continue
})
I'm studying on my own, so I will be very grateful to you :)
The .map() function will go through the entire array, and on each step of that process it will take the current item that we are looking at and will pass it as a parameter into the function. You can then do whatever you want to that item, and whatever you return from your function will replace what is in that position in the array.
Say for example, with the array you gave in your question, we wanted to remove the name and last_name properties, and combine them into a full_name property. We can do the following:
let people = [
{
id: 1,
name: 'jhon',
last_name: 'wilson'
},
{
id: 2,
name: 'maria',
last_name: 'anyway'
},
id: 3,
name: 'lastOne',
last_name: 'example'
}
];
people = people.map((person) => {
return {
id: person.id,
full_name: `${person.name} ${person.last_name}`
}
});
After this code runs, our people array would look like this:
[
{
id: 1,
full_name: 'jhon wilson'
},
{
id: 2,
full_name: 'maria anyway'
},
id: 3,
name: 'lastOne example'
}
];
You can think of it as doing something very similar to this:
function transformPerson(person) {
return {
id: person.id,
full_name: `${person.name} ${person.last_name}`
}
}
let newPeople = [];
for (let i = 0; i < people.length; i++) {
newPeople[i] = transformPerson(people[i])
}
people = newPeople;
Array.map() takes in a function as a parameter, passes each item of the array into the function, and returns an array of the result.
For example, if I wanted to multiply each of the items in the array by 2:
const x = [1, 2, 3, 4, 5]
const y = x.map(v => v * 2) // result: [2, 4, 6, 8, 10]
Note: Array.map does not affect the original array; it creates a new array of the results.
You could change your code to
let people = [{id:1,name:'john',last_name:'wilson'},{id:2,name:'maria',last_name:'anyway'},{id:3,name:'lastOne',last_name:'example'}];
people = people.map((p,i) =>({...p,name: i===1?prompt("New name"):p.name}))
console.log(people);
This will prompt the user only for a new name when i===1. The expression will create a new array that will be stored under the variable name people again. If you wanted people to remain unchanged you could assign the return value of the people.map()-call to a different variable (or constant).

Adding values to an object within an Array inside a FOR loop

I have an array extracted from Mongo in the following form
[
{
_id: 60d51d210e5e4e297066132a,
MemberName: 'Name of Member',
MemberRank: 25,
MemberFDR: 6.43,
MemberImageurl: 'uploads/images/gauravverma.jpg'
},
{
_id: 60d5c619c163f23195e01d00,
MemberName: 'Name Of Member',
MemberRank: 24,
MemberFDR: 6.5,
MemberImageurl: 'uploads/images/shashikhanna.jpeg'
},
]
After extracting the original array, I am looping through the array, extracting the name of the member and then doing some more queries in the DB. The length of this returned query, is the count and I want to add it in the original object like so
[
{
_id: 60d51d210e5e4e297066132a,
MemberName: 'Name of Member',
MemberRank: 25,
MemberFDR: 6.43,
MemberImageurl: 'uploads/images/gauravverma.jpg',
Count: 3(whatever the length of the array will be)
},
{
_id: 60d5c619c163f23195e01d00,
MemberName: 'Name Of Member',
MemberRank: 24,
MemberFDR: 6.5,
MemberImageurl: 'uploads/images/shashikhanna.jpeg'
Count: 5(whatever the length of the array will be)
},
]
My query returns the value perfectly, I am struggling with how to insert the value in the original object.
let memberName
let countOfCurrentChallengeMatches
for(let i=0; i<challengeList.length; ){
console.log("hi i am here 1")
memberName = challengeList[i].MemberName
console.log(memberName)
try {
console.log(memberName)
countOfCurrentChallengeMatches = await MatchRegister.find({
$and: [
{ $or: [{ChallengingPlayer: memberName},{ChallengedPlayer: memberName}] },
{ $or: [{ChallengeStatus: 'Awaiting Score Approval'},{ChallengeStatus: 'Accepted'},{ChallengeStatus: 'Completed'}, {ChallengeStatus: 'Issued'}] },
{ChallengerMonth: cMonth},
],
},'_id ChallengingPlayer ChallengedPlayer ChallengerMonth ChallengerYear ProposedChallengeDate ProposedChallengeTime ChallengeMatchLocation ChallengeStatus MatchFormat RejectionReason')
.sort({ProposedChallengeDate: 1}).exec()
} catch (err) {
const error = new HttpError(
'Something went wrong, could not update member.',
500
);
return next(error);
}
// Here is where i want to insert the value in the object
i++
}
I have tried options like, push, add and a few other options from google, but nothing works.
Just example below. Have you tried this example yet?
var arrOfObj = [{
name: 'eve'
}, {
name: 'john'
}, {
name: 'jane'
}];
var result = arrOfObj.map(function(el) {
var o = Object.assign({}, el);
o.isActive = true;
return o;
})
console.log(arrOfObj);
console.log(result);
Hey this simple line worked. Not sue why I missed it in my research
challengeList[i].count = countOfCurrentChallengeMatches.length

How to convert an array of URLs into a tree/folder structure data?

For start I have an array of URLs which I have crawled using a simple-crawler library.
The data received is what I want to transform into a tree structure or folder structure.
I am using react-tabulator here because I wanted to resize columns of table.
Now along with normal table, I want to have the nested folder view structure.
//input data
const urls = [
{ id: 1, address: 'https://happy.com' },
{ id: 2, address: 'https://happy.com/about' },
{ id: 3, address: 'https://happy.com/contact' },
{ id: 4, address: 'https://happy.com/contact/office' },
{ id: 5, address: 'https://happy.com/contact/home' },
{ id: 6, address: 'https://happy.com/projects' },
];
//output data
tableDataNested = [
{ id: 1, address: 'https://happy.com',
_children:[
{ id: 2, address: 'https://happy.com/about', _children:[] },
{ id: 3, address: 'https://happy.com/contact',
_children:[
{ id: 4, address: 'https://happy.com/contact/office', _children:[] },
{ id: 5, address: 'https://happy.com/contact/home', _children:[] },
]
},
{ id: 6, address: 'https://happy.com/projects', _children:[] },
]
}
];
Though I saw 1-2 posts resembling this concept, I wasn’t sure on the pure JS way of doing or probably use some nice libraries too.
Any insights anyone?
You can just split the URL-s along the last slash (there always will be one here because of the //: part) and use a Map to track containment relations:
const urls = [
{ id: 1, address: 'https://happy.com' },
{ id: 2, address: 'https://happy.com/about' },
{ id: 3, address: 'https://happy.com/contact' },
{ id: 4, address: 'https://happy.com/contact/office' },
{ id: 5, address: 'https://happy.com/contact/home' },
{ id: 6, address: 'https://happy.com/projects' },
];
const tableDataNested = [];
const prefixmap = new Map();
for(let url of urls) {
url._children = []; // extend node with the array
let address = url.address;
let lastslash = address.lastIndexOf('/');
let prefix = address.substring(0,lastslash);
if(prefixmap.has(prefix)) { // has parent, so add to that one
prefixmap.get(prefix)._children.push(url)
} else { // toplevel node
tableDataNested.push(url);
}
prefixmap.set(address,url); // store as potential parent in any case
}
console.log(tableDataNested);
This snippet actually modifies the original objects (in urls), but of course it's also possible to make a copy if needed, something like
url = {id:url.id,address:url.address,_children:[]};
instead of url._children = [];
Before I answer this question, I must give a fair warning that this question is broad and moderators usually flag them.
Luckily, the solution that you're looking for is alsocalled a "tree" in UI design terminologies. I found a few:
https://material-ui.com/components/tree-view/
The catch here is, you've to use material-ui library for this (my assumption)
https://reactjsexample.com/a-hierarchical-object-tree-component-for-react/
This one has a github page too & a codesandbox live working example too
Another, https://reactjsexample.com/a-themable-and-configurable-treeview-for-react/
Hope, this helps.

How can i display more than one array elements that satisfy a condition?

How can I display multiple values of an array to the console that match the condition (e.g: === "McDonalds")?
I only managed to display one item. But I don't know how i can display all the value of my array.
public products: product[] = [
{ id: 1, name: "McFlurry", price: 2, enseigne:"McDonalds" },
{ id: 2, name: "Potatoes", price: 3, enseigne:"McDonalds" },
{ id: 3, name: "BigMac", price: 4, enseigne:"KFC" },
{ id: 4, name: "Nuggets", price: 3, enseigne:"KFC" }
];
searchEnseigne(){
let server = this.products.find(x => x.enseigne === "McDonalds");
console.log(server);
}
let server = this.products.filter(x => x.enseigne === "McDonalds");
console.log(server);
Use filter instead of find:
The filter() method creates a new array with all elements that pass the test. While The find() method returns the value of the first element
searchEnseigne(){
let server = this.products.filter(x => x.enseigne === "McDonalds");
console.log(server);
}

Angularjs - Fetch object in ng-repeat

I have 2 separate json objects coming from the server. Json A below is of a Car model object which is fetch when looking at a car. Json B is meta data which is used throughout the whole application when the web page first loads.
What I need to do is have a lookup on wheel_id while doing a ng-repeat on wheel_handlers so it returns the wheel object from json B and then I can use this within the view and print the results. I think I need to do something with the ng-repeat but I'm not sure to be honest.
A - Car model
[{
id: 14,
name: "Audi",
wheel_handlers: [
{
id: 9,
wheel_id: 62,
arguments: {
amount: 10
}
}
]
}]
B - wheel
{
id: 62,
name: "Change Wheel Size",
arguments: [
{
id: 25,
description: "amount"
}
]
}
I am assuming the following: The Json "A" may include several cars, but also several wheel_handlers (because there is an array at wheel_handler). So the JSON for the cars may also look like this:
[
{
id: 14,
name: "Audi",
wheel_handlers: [
{
id: 9,
wheel_id: 62,
arguments: {
amount: 10
}
},
{
id: 12,
wheel_id: 65,
arguments: {
amount: 12
}
},
{
id: 15,
wheel_id: 30,
arguments: {
amount: 8
}
}
]
},
{
id: 16,
name: "Mercedes",
wheel_handlers: [
{
id: 9,
wheel_id: 62,
arguments: {
amount: 10
}
},
{
id: 12,
wheel_id: 65,
arguments: {
amount: 12
}
}
]
}
]
For the JSON file B I assume that you also meant an Array, which could contain several wheel definitions. As an example:
[
{
id: 62,
name: "Change Wheel Size",
arguments: [
{
id: 25,
description: "amount"
}
]
},
{
id: 65,
name: "test wheel",
arguments: [
{
id: 25,
description: "amount"
}
]
},
{
id: 30,
name: "another wheel",
arguments: [
{
id: 25,
description: "amount"
}
]
}
]
If this is the case, you could iterate over the cars and while iterating call a helper function in the AngularJS controller. You call this helper function and give wheel_handlers of the current car as a parameter. This helper function then checks the wheel_id of each wheel_handler entry and searches these ids in the JSON b file - the wheel definitions. The helper function returns an array containing the wheels, so in the view you may iterate over the wheels. This will use a nested ng-repeat, because at first you iterate over the cars and while iterating over the cars you will iterate over the wheels.
Here is an example of the controller part. I used $scope.cars as the JSON A, and $scope.wheels as JSON B.
var testApp = angular.module('testApp', []);
testApp.controller('testContr', function ($scope) {
$scope.cars = [];
$scope.wheels = [];
$scope.getWheelsByIds = function (wheel_handlers) {
var wheelIds = [];
var returnArray = [];
for (var wheelKey in wheel_handlers) {
wheelIds.push(wheel_handlers[wheelKey].wheel_id);
}
for (var key in $scope.wheels) {
console.log(wheelIds.indexOf($scope.wheels[key].id));
if (wheelIds.indexOf($scope.wheels[key].id) > -1) {
returnArray.push($scope.wheels[key]);
}
}
return returnArray;
}
});
The necessary HTML part could look like this:
<div ng-app="testApp" ng-controller="testContr">
<div ng-repeat="car in cars" ng-init="wheels = getWheelsByIds(car.wheel_handlers)">
<span>Car name: {{car.name}}</span><br/>
<div ng-repeat="wheel in wheels">
<span>Wheel name: {{wheel.name}}</span><br/>
</div>
<br/>
<br/>
</div>
</div>
I create a fiddle demonstration with the test data, view it here: http://jsfiddle.net/4F3YD/10/
You can nest ng-repeats like that, although I'm not sure what you want to achieve
following code will repeat through cars, then wheels in cars and display wheels from object B(wheels) that match the car wheel id, hope that makes sense
<div ng-repeat="car in CarModels">
<div ng-repeat="wheel in car.wheel_handlers">
{{Wheels | filter:wheel.wheel_id}}
</div>
</div>
You can make use of angular filter over here. In the filter function you can check for the id in the second json.
More Documentation on Angular Filter
Code Example:
<div ng-repeat="element in wheel | filterIds:element.id">
And filter Function:
.filter('filterIds', function () {
return function(id) {
$scope.carModel.forEach(function(car){
if(id == car.id)
return id;
});
}
})

Categories