Can someone explain the flow of steps that are happening here? - javascript

I'm trying to figure out is each item going through reduce as the map runs, or is the map method running completely, and then after it returns the array, the reduce method is being applied to the array from the map?
const lineItems = [
{ description: 'Eggs (Dozen)', quantity: 1, price: 3, total: 3 },
{ description: 'Cheese', quantity: 0.5, price: 5, total: 2.5 },
{ description: 'Butter', quantity: 2, price: 6, total: 12 }
];
let store = lineItems.map(item => item.quantity).reduce(sumReducer, 0);
function sumReducer(sum, val) {
return sum += val;
}
console.log(store);

All regular - non generator - functions in javascript have run-to-completion semantics. This means that when they are called, the execute until they return without interruption.
In this case the map() function executes and returns an array, then the reduce() function executes.

Related

Can someone explain this for/in loop to me?

/*
Write each function according to the instructions.
When a function's parameters reference `cart`, it references an object that looks like the one that follows.
{
"Gold Round Sunglasses": { quantity: 1, priceInCents: 1000 },
"Pink Bucket Hat": { quantity: 2, priceInCents: 1260 }
}
*/
function calculateCartTotal(cart) {
let total = 0;
for (const item in cart){
let quantity = Object.values(cart[item])[0];
let price = Object.values(cart[item])[1];
total += price * quantity;
}
return total;
}
function printCartInventory(cart) {
let inventory = "";
for (const item in cart){
inventory += `${Object.values(cart[item])[0]}x${item}\n`;
}
return inventory;
}
module.exports = {
calculateCartTotal,
printCartInventory,
};
The part that confuses me is the function calculateCartTotal. What I am confused about is how does this loop know to grab priceInCents? for example, if I was to add another value into the object called "weight: 24" assuming that it is 24 grams, how does the object value skip over quantity and weight and just grab priceInCents? Hopefully I am making sense on how I am confused and that someone has an explanation for me!
If you try to run below program then it will be easier for you to visualize everything.
What is happening is item is just the index of element and for an object we can either use the key name to access its value or its index.
You can read this doc to understand what Object.values() does.
function calculateCartTotal(cart) {
let total = 0;
for (const item in cart) {
console.log(item)
let quantity = Object.values(cart[item])[0];
let price = Object.values(cart[item])[1];
total += price * quantity;
}
return total;
}
var cart = [
{
quantity: 2,
price: 5,
weight: 24
},
{
quantity: 3,
price: 10,
weight: 90
},
{
quantity: 7,
price: 20,
weight: 45
},
{
quantity: 1,
price: 100,
weight: 67
}
]
console.log(calculateCartTotal(cart))
OUTPUT:
0
1
2
3
280
Program 2 to demonstrate what is happening
function calculateCartTotal(cart) {
console.log(Object.values(cart[2])[1])
console.log(cart[2]['price'])
console.log(cart[2].price)
}
var cart = [
{
quantity: 2,
price: 5,
weight: 24
},
{
quantity: 3,
price: 10,
weight: 90
},
{
quantity: 7,
price: 20,
weight: 45
},
{
quantity: 1,
price: 100,
weight: 67
}
]
calculateCartTotal(cart)
OUTPUT:
20
20
20
I am Deepak,🙂
I can explain (program 2 demonstration). See my friend,you will be able to see the first console.log i.e, console.log(Object.values(cart[2])[1])...
So, object means the whole cart and .values means the only numbers that a particular object contained. Now, see the result i.e, 20.
So, how this 20 will came?...
Now, see the console.log that I have written before. In the brackets of .value cart of [2](it means that 2 is the position of that cart, that why it is written as cart[2] i.e, inside a cart 2nd position's object and after cart[2] this one number is there [1], it means inside the 2nd position's object i.e,
OBJECT below:- position of an objects
var cart = [
quantity: 2, 0 position
price: 5,
weight: 24
},
{
quantity: 3, 1 position
price: 10,
weight: 90
},
{
quantity: 7, 2 position
price: 20,
weight: 45
} ,
{
quantity: 1, 3 position
price: 100,
weight: 67
}
]
console.log(calculateCartTotal(cart))
Now, match the console.log.
it says that console.log(OBJECT.values(cart[2])[1]);
In the cart, see the 2nd position's object i.e,
{
quantity: 7, 2 position
price: 20,
weight: 45
}
So, cart[2] means the whole object you will above.
[1] means inside the object count the position from 0 onwards. So, in the
values
0 position quantity, 7,
1 position price, 20,
2 position weight. 45.
In the [1] position price: 20.
So, cart[2] means
{
quantity: 7, 2 position
price: 20,
weight: 45
}
And,
[1] means price: 20.
So, your answer is 20.
Note: the numbers that is inside the square brackets will gives the position of an object or inside an object.

.map usage in an object

just wondering if someone could point me in the right direction of .map functionality. This is unfortunately something I'm struggling to get my head around.
If I had an object, lets say the following:
const myPetsAndFood = {
pets:[
{
species: "dog",
breed: "Labrador",
age: 12
},
{
species: "cat",
breed: "unknown",
age: 7,
},
{
species: "fish",
breed: "goldfish",
age: 1,
}
],
food: [
{
dogfood: 15.00,
},
{
catfood: 11.00,
},
{
fishfood: 4.00,
}
],
};
Could anyone explain how I'd utilise .map to obtain the data values of age and price if possible please?
A brief explanation or example is more than suffice, I'd appreciate any time/input possible. In all probability, I'll be sat here reading and trying to figure it out in the mean time.
If you got this far - Thank you for your time.
So the .map can only be used with arrays. This way you can not do something similar to:
myPetsAndFood.map()
Let's say you want do console.log the age. You would have to get the array first. So:
myPetsAndFood.pets.map((pet) => {
console.log(pet.age)
})
And it would print 12, followed by 7 followed by 1. If you want to store it inside an array you can create an array and use .push("//infos wanted to be pushed//")
Object.keys(myPetsAndFood).map(function(key, index) {
console.log(myPetsAndFood[key][0].dogfood);
console.log(myPetsAndFood[key][0].age);
});
You are going to have to figure out a way to replace the 0 with some sort of counter that will increment.
map is a method of arrays, it doesn't exist on objects. You could use it on the arrays within the object ( myPetsAndFood.pets.map( /* ... */ ) ) but you'd have to use a for loop or some other technique to parse each item in the object.
An example of how to use the map function for one of your arrays:
const agesArray = myPetsAndFood.pets.map((item) => {
return item.age;
});
So you have imbricated arrays here. This makes it so you have to go into your wanted array first before being able to execute your map.
For example: myPetsAndFood.pets.map(function)
The way that .map works is it executes your function on every element in your array and returns an array with the equivalency(source).
Therefore, in order to get the age of every pet, you have to tell your function to get your age property of your objects.
For example: myPetsAndFood.pets.map((pet) => pet.age)
This will return an array containing only the age of every one of your pets.
Now the problem with this is your second array. We cannot call the .map function on that array because your different properties don't have the same name. Therefore, your .map won't have any common ground to return a sensible array.
We can fix this issue by splitting your one variable into two: name and price for example. After this change, we can now call the .map on your array properly by telling it which property you need.
For example: myPetsAndFood.foods.map((food) => food.price)
Below is a full code snippet which should show off the above description.
const myPetsAndFood = {
pets:[
{
species: "dog",
breed: "Labrador",
age: 12
},
{
species: "cat",
breed: "unknown",
age: 7,
},
{
species: "fish",
breed: "goldfish",
age: 1,
}
],
foods: [
{
name: "dog",
price: 15.00,
},
{
name: "cat",
price: 11.00,
},
{
name: "fish",
price: 4.00,
}
],
};
const catAge = myPetsAndFood.pets.map((pet) => pet.age)
const foodPrice = myPetsAndFood.foods.map((food) => food.price)
console.log(catAge)
console.log(foodPrice)

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).

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);
}

Comparing partial objects in ramda.js

There is an equals function in Ramdajs which is totally awesome, it will provide the following:
// (1) true
R.equals({ id: 3}, { id: 3})
// (2) true
R.equals({ id: 3, name: 'freddy'}, { id: 3, name: 'freddy'})
// (3) false
R.equals({ id: 3, name: 'freddy'}, { id: 3, name: 'freddy', additional: 'item'});
How would I go about enhancing this function, or in some other way produce a true result for number 3
I would like to ignore all the properties of the rValue not present in the lValue, but faithfully compare the rest. I would prefer the recursive nature of equals remain intact - if that's possible.
I made a simple fiddle that shows the results above.
There's a constraint on equals in order to play nicely with the Fantasy Land spec that requires the symmetry of equals(a, b) === equals(b, a) to hold, so to satisfy your case we'll need to get the objects into some equivalent shape for comparison.
We can achieve this by creating a new version of the second object that has had all properties removed that don't exist in the first object.
const intersectObj = (a, b) => pick(keys(a), b)
// or if you prefer the point-free edition
const intersectObj_ = useWith(pick, [keys, identity])
const a = { id: 3, name: 'freddy' },
b = { id: 3, name: 'freddy', additional: 'item'}
intersectObj(a, b) // {"id": 3, "name": "freddy"}
Using this, we can now compare both objects according to the properties that exist in the first object a.
const partialEq = (a, b) => equals(a, intersectObj(a, b))
// again, if you prefer it point-free
const partialEq_ = converge(equals, [identity, intersectObj])
partialEq({ id: 3, person: { name: 'freddy' } },
{ id: 3, person: { name: 'freddy' }, additional: 'item'})
//=> true
partialEq({ id: 3, person: { name: 'freddy' } },
{ id: 3, person: { age: 15 }, additional: 'item'})
//=> false
Use whereEq
From the docs: "Takes a spec object and a test object; returns true if the test satisfies the spec, false otherwise."
whereEq({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy', additional: 'item' })
The other way around is to develop your own version. It boils down to:
if (is object):
check all keys - recursive
otherwise:
compare using `equals`
This is recursive point-free version that handles deep objects, arrays and non-object values.
const { equals, identity, ifElse, is, mapObjIndexed, useWith, where } = R
const partialEquals = ifElse(
is(Object),
useWith(where, [
mapObjIndexed(x => partialEquals(x)),
identity,
]),
equals,
)
console.log(partialEquals({ id: 3 }, { id: 3 }))
console.log(partialEquals({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy' }))
console.log(partialEquals({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy', additional: 'item' }))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
I haven't used Ramda.js before so if there's something wrong in my answer please be free to point out.
I learned the source code of Ramda.js
In src/equals.js, is where the function you use is defined.
var _curry2 = require('./internal/_curry2');
var _equals = require('./internal/_equals');
module.exports = _curry2(function equals(a, b) {
return _equals(a, b, [], []);
});
So it simply put the function equals (internally, called _equals) into the "curry".
So let's check out the internal _equals function, it did check the length in the line 84~86:
if (keysA.length !== keys(b).length) {
return false;
}
Just comment these lines it will be true as you wish.
You can 1) just comment these 3 lines in the distributed version of Ramda, or 2) you can add your own partialEquals function to it then re-build and create your version of Ramda (which is more recommended, from my point of view). If you need any help about that, don't hesitate to discuss with me. :)
This can also be accomplished by whereEq
R.findIndex(R.whereEq({id:3}))([{id:9}{id:8}{id:3}{id:7}])

Categories