Can someone explain this for/in loop to me? - javascript

/*
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.

Related

Use For loop to iterate through array of objects to get the greatest Balance

const bankAccounts = [
{
id: 1,
name: "Susan",
balance: 100.32,
deposits: [150, 30, 221],
withdrawals: [110, 70.68, 120],
},
{ id: 2, name: "Morgan", balance: 1100.0, deposits: [1100] },
{
id: 3,
name: "Joshua",
balance: 18456.57,
deposits: [4000, 5000, 6000, 9200, 256.57],
withdrawals: [1500, 1400, 1500, 1500],
},
{ id: 4, name: "Candy", balance: 0.0 },
{ id: 5, name: "Phil", balance: 18, deposits: [100, 18], withdrawals: [100] },
];
function getClientWithGreatestBalance(bankAccounts) {
const maxAccount = bankAccounts[0];
const newArr = [];
for (let i = 0; i < array.length; i++) {
if (bankAccounts[i].balance > maxAccount.balance)
newArr.push([i]);
}
return newArr;
}
I am trying to loop through the bankAccounts array to get the object that has the greatest balance and push that object into the new array and return that single account.
I know I need to check the balance of each account but for some reason can not figure out how to get the single object.
I guess that array variable you are using in the for loop is meant to be bankAccounts, and at first it seemed weird to me that you are returning an array then I thought that you may have wanted to return an array in case there are multiple accounts that share the max balance. So, with that in mind your function should be something like this
function getClientWithGreatestBalance(bankAccounts) {
let maxBalance = 0;
let maxBalanceAcounts = [];
for (let i = 0; i < bankAccounts.length; i++) {
if (bankAccounts[i].balance > maxBalance){
maxBalance = bankAccounts[i].balance;
maxBalanceAcounts = [];
maxBalanceAcounts.push(bankAccounts[i])
}
else if (bankAccounts[i].balance === maxBalance){
maxBalanceAcounts.push(bankAccounts[i])
}
}
return maxBalanceAcounts;
}
You can't know which is the biggest until you've seen all of them, so it doesn't make sense to push anything to your output array until the end.
Instead, you need to keep track of the account with the biggest balance of those you've seen so far. So instead of an array, you want a single variable to track that one.
In fact you already have that variable, maxAccount. So if you find an account with a bigger balance than maxAccount.balance, you want to set maxAccount to the new account, instead of the previous max.
Once you have finished the loop, then you can push that to your output array (assuming you even need an output array, since you are always just returningg one).
Other points about your code:
getClientWithGreatestBalance will crash if you give it an empty input array.
You are starting by assuming (temporarily) that the first account is the biggest - which is OK, but then you are starting a loop at the first account, so the first time round the loop is comparing the first account to itself, which is unnecessary (but won't cause any errors).
It's better to iterate over an array directly rather than by index. Again, your code isn't wrong in that respect, but over-complicated.
for (let account of array) {
// ...
}

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

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.

Sorting into groups of 40

I need a program that can take input from a user with data quantities and length (feet and inches or just inches) and group the items into groups of 40.
I originally started trying to accomplish this in Excel, but I'm not sure it can be done.
var cutList = [
{ qty: 36, feet: 28, inch: 3 },
{ qty: 6, feet: 27, inch: 8 },
{ qty: 12, feet: 27, inch: 3 },
{ qty: 6, feet: 25, inch: 8 },
{ qty: 16, feet: 25, inch: 3 },
{ qty: 22, feet: 22, inch: 8 },
{ qty: 12, feet: 12, inch: 3 },
];
Group 1 would have all 36 from the first item plus 4 from the second.
Group 2 would have the remaining 2 items from the second line plus all 12 from the 3rd, and down the line until 40 is hit again. It's been a while since I've done any programming, but I was hoping I could do something like this in JavaScript and embed it in an HTML file for people to use. Ideally they'd be able to copy and paste the data from an Excel spreadsheet into this.
There was an answer posted on Friday that I've been playing with and it seems to work. I don't know if it was deleted or edited but I don't see it now. Here is the code:
var cutList = [ { qty: 36, feet: 28, inch: 3 },
{ qty: 6, feet: 27, inch: 8 },
{ qty: 12, feet: 27, inch: 3 },
{ qty: 6, feet: 25, inch: 8 },
{ qty: 16, feet: 25, inch: 3 },
{ qty: 22, feet: 22, inch: 8 },
{ qty: 12, feet: 12, inch: 3 }],
limit = 40,
used = 0,
result = cutList.reduce((r, { qty, feet, inch }, i) => {
var rest, min;
while (qty) {
if (used === 0) r.push([]);
min = Math.min(limit - used, qty)
r[r.length - 1].push({ qty: min, feet, inch, limit });
qty -= min;
used += min;
if (used === limit) used = 0;
}
return r;
}, []);
console.log(result);
So to whoever posted this on Friday, Thank You.
My interpretation of the requirement follows.
// input:
var cutList = [
{ qty: 36, feet: 28, inch: 3 },
{ qty: 6, feet: 27, inch: 8 },
{ qty: 12, feet: 27, inch: 3 },
{ qty: 6, feet: 25, inch: 8 },
{ qty: 16, feet: 25, inch: 3 },
{ qty: 22, feet: 22, inch: 8 },
{ qty: 12, feet: 12, inch: 3 },
]
// proposed output:
let manifest = [
{batchName:A, batch: [{feet: 12, inch: 3}, ... to 40]},
{batchName:B, batch: [{}, {}, {}, ... to 40]},
{batchName:C, batch: [{}, {}, {}, ... to 40]}
]
If the above datagram accurately reflects what you're looking for then the pseudocode can be completed, as both precursor to writing test cases and the algorithm.
// pseudo:
.get line {cutListItem}, sequentially
.set {runningTotal}
.write new {batchName} to {manifest}
do while
.test {cutListItemQty} !== 0
.enumerate decremeent (--) {cutListItemQty} from {cutListItem}
while {runnintTotal} + {qty} in {cutListItem} <= {batchSizeLimit}
do .write to {manifest}
do until either condition:
{cutListItemQty} from {custListItem} === 0
.read {cutList} .get next {cutListItem}
{runningTotal} === {batchSizeLimit}
.init {runningTotal}
.loopback new {batchName}
// considerations
With the sequential method, A chief benefit is being able to stop at any time to then add or change entries which have not yet been processed. Generally, sequential processing offers better overall workflow integration, too, being able to fit asynchronously into a larger process involving the flow of data from creation through various mutations of use. Potential loss is minimized to what remains of the generated list and its progenitor cutlist entries.
At the level of final processing {qty} would be aggregated into batch, and dropped from the datagram, but you might want a reference to the ids of the originating cutlist entries contained in each batch. That speaks to your cutlist, outlining the potential need for identifiers on each entry. We're simply mapping rows and columns here... So, to extend the datagram layout, I'm wondering how you'd view, say, another array entry for each batch, something like: {originsList: [id#3, id#1, id#...], ...}?
I've learned a lot here, so I feel you're in the right place to discover how to put together a working model of your data for a site. And given the programming language internal data type match to your cutlist, from a technical perspective, you appear to be on the right track.
Edit:
The following doesn't hold a candle to what is an artfully concise and complete answer provided by Nina Scholz. Reading her elegant submission again, and comparing it to the original question, I learned my understanding of the problem was limited, as she deeply dives into a min/max solution.
She sets the bar high, and it is a pleasure to read her work. I will continue to learn from that depth of insight as my practical knowledge of Javascript matures in terms of control flow and data structures.
In any case, my code follows:
let cutList = [
{ qty: 36, feet: 28, inch: 3 },
{ qty: 6, feet: 27, inch: 8 },
{ qty: 12, feet: 27, inch: 3 },
{ qty: 6, feet: 25, inch: 8 },
{ qty: 16, feet: 25, inch: 3 },
{ qty: 22, feet: 22, inch: 8 },
{ qty: 12, feet: 12, inch: 3 },
]
// add id field to cutlist retaining this in the array for check against final manifest entries
cutList.filter((item) => item.qty !== 0).forEach((item, idx) => {item.id = idx + 1})
// could expand objects in number of qty to this or new array, keeping original array entries
// Or, decrement the item.qty as each new replica is made with item.subId as an identifier
let qtyTotal = 0
let pooled = []
// console.log(cutList)
// expand cutlist entries by qty to new array, pooled, adding subId to each entry
let arrays = cutList.map((item, idx) => {
// forEach works here, probably better, too - lots of bloatiness going on in either case, trails of replicated lists, not a good production solution
// aggregate entry qty for a total as each entry(item) is parsed
qtyTotal += item.qty
for (let i = 0; i < item.qty; i++) {
let o = {}
o = Object.assign(o, item)
o.subId = i
o.id - i
// console.log(o) // console.dir(o) would be better
pooled.push(o)
}
return pooled
})
// the list manifest will be chunked from
// console.dir(pooled)
// console.log('arrays.length: ', arrays.length)
// make sure the sum of qty matches the number
let valid
if (qtyTotal === pooled.length) {
valid = true
} else {
valid = false
}
console.log(`qty total: ${qtyTotal} pooled total: ${pooled.length}
The manifest data is ${valid ? 'ready.' : 'not ready for use.' }`)
// no exit, program continues
console.log("Producing manifest...")
// chunk pool by batchsize
let chunkedList = []
function produceManifest(start, batchsize) {
let i = start
let k = 0
do {
let qty, feet, inch, id, subId
let x = []
let j = 0
do {
// assign objects from the pool into batchsized arrays
// console.dir(pooled[i]);
// if (typeof pooled[i] === undefined) break;
try {
({qty, feet, inch, id, subId} = pooled[i])
i ++
} catch(e) {
// console.error(e)
// break
}
x[j] = {qty, feet, inch, id, subId}
// console.log(x[j])
j ++
if (i >= pooled.length) break;
// console.log("getting j: " + j)
} while (j <= batchsize - 1) // index in reference array starts at 0
chunkedList[k] = [...x]
// chunkedList.push[x]
// console.dir(chunkedList)
k ++
} while (i <= pooled.length - 1)
// console.dir(chunkedList)
return chunkedList
}
// manifest is an array containing batches of the number requested
// do the job
let start = 0
let batchsize = 40
let printable = produceManifest(start, batchsize)
console.dir(printable)
console.log('debug')

To group of array of objects by its id value

I have a group of array of objects in which that object property has value with ID number. I am successfully group it with that ID, however I am doing it by hardcode, not dynamically.
var objBuyUser = response.newIdUserPul[i].arrayUserHistoryBuy;
for (var y = 0; y < objBuyUser.length; y++) {
if(objBuyUser[y].product_id == 1) {
var doesIdExist = vm.pulBms.filter(function(v) {
return v.userid === response.newIdUserPul[i].id;
});
if(doesIdExist.length > 0) {
//do nothhing
} else {
vm.pulBms.push({
userid:response.newIdUserPul[i].id,
buyAct: objBuyUser
});
}
}
objBuyUser[y].product_id == 1 is what will different them each other. As long as this time we only have three ID number 1, 2, 3, I just copied the same code by changing the id manually. So, anybody can help to make it dynamically?
(**)SO: actually we have the list of product: 1, 2, 3
In the backend, I have process a unique user with its history buy, assign by response.newIdUserPul[i]. And the arrayUserHistoryBuy is the array of object detailing their product history buying from the range of the date, which in the object can consiste the date, quantity, and the product_id which need to be group here (reffer to -> **). In this case, knowing that each user can buy different product in the range of date, we still group it by product since the product is exist in the history of buying.
So the output could be similar like this:
ProductID1 :
{
User: 123
ProductBuyHistory :
{
Date: 3-10-10
ProductID : 2,
Quantity: 10
},
{
Date: 4-10-10
ProductID : 1,
Quantity: 10
},
},
{
User: 124
ProductBuyHistory :
{
Date: 3-10-10
ProductID : 3,
Quantity: 10
},
{
Date: 4-10-10
ProductID : 1,
Quantity: 10
},
},
SO on for productId 2 and 3

Gridster serialize data to 1-5 order (recursive loop)?

I'm using the Gridster plugin, and I need to capture the newly dragged order in an 1-5 manner. I know that we choose row first, then order (column). So, row:1, order:1 would be id: grid_74. The next closest order number greater than 1 in row 1 is 5, so id: grid_78. How can I accomplish this?
1 - grid_74
2 - grid_78
(etc...)
var gridinfo = gridster.serialize()
I think you might just need a sort.
// Just setting up object array to match example:
var gridinfo = [
{ id: "grid_75", order: 5, row: 4 },
{ id: "grid_74", order: 1, row: 1 },
{ id: "grid_91", order: 9, row: 1 },
{ id: "grid_85", order: 5, row: 7 },
{ id: "grid_78", order: 5, row: 1 }
]
// This sort is what does all the magic.. it first sorts by row, then order.
// I lifted this bit of javascript ninjutsu from:
// http://www.sitepoint.com/sophisticated-sorting-in-javascript/
gridinfo.sort(function(a, b)
{
if(a.row === b.row)
{
return a.order < b.order ? -1 : a.order > b.order ? 1 : 0;
}
return a.row - b.row;
});
// Display sorted array:
for(var k=0; k<gridinfo.length; k++)
{
document.write('id: '+gridinfo[k].id+'<br>');
document.write('row: '+gridinfo[k].row+'<br>');
document.write('order: '+gridinfo[k].order+'<br>');
document.write('-------<br>');
}

Categories