Refactor traversing over an array of objects using spread operator - javascript

function main() {
let yesterdaysOrders = [
{
id: 1,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 02",
quantity: 3
},
{
itemName: "Item 03",
quantity: 25
},
{
itemName: "Item 04",
quantity: 12
},
],
},
{
id: 2,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 08",
quantity: 42
},
{
itemName: "Item 09",
quantity: 13
},
{
itemName: "Item 12",
quantity: 37
},
],
},
{
id: 3,
orderLines: [{
itemName: "Item 12",
quantity: 16
}, ],
},
{
id: 4,
orderLines: [{
itemName: "Item 10",
quantity: 11
},
{
itemName: "Item 11",
quantity: 10
},
],
},
{
id: 5,
orderLines: [{
itemName: "Item 06",
quantity: 7
},
{
itemName: "Item 07",
quantity: 2
},
{
itemName: "Item 12",
quantity: 14
},
],
},
{
id: 6,
orderLines: [{
itemName: "Item 05",
quantity: 17
}, ],
},
{
id: 7,
orderLines: [{
itemName: "Item 03",
quantity: 5
},
{
itemName: "Item 07",
quantity: 2
},
],
},
{
id: 8,
orderLines: [{
itemName: "Item 02",
quantity: 13
},
{
itemName: "Item 07",
quantity: 7
},
{
itemName: "Item 09",
quantity: 2
},
],
},
{
id: 9,
orderLines: [{
itemName: "Item 01",
quantity: 4
},
{
itemName: "Item 06",
quantity: 17
},
{
itemName: "Item 07",
quantity: 3
},
],
},
{
id: 10,
orderLines: [{
itemName: "Item 11",
quantity: 12
},
{
itemName: "Item 12",
quantity: 1
},
],
}
],
result = Array.from(
yesterdaysOrders.reduce((acc, {
orderLines
}) => {
orderLines.forEach(({
itemName,
quantity
}) => acc.set(itemName, (acc.get(itemName) || 0) + quantity));
return acc;
}, new Map), ([itemName, quantity]) => ({
itemName,
quantity
}));
}
I have this function and at the end, I'm grabbing the itemName and quantity so that eventually I can display them in the DOM.
I'm looking to refactor the result = Array.from.... to be used with a spread operator, along with the already implemented destructuring.
How would I go about starting this off?
I'm understanding that the spread operator allows anything that is iterable to be able to be expanded.
Also, within the main function, after I place the comma and define my new function with result, what is the explanation for not needing a var, let, or const before it?

Related

Sum up values of identical objects' property in Javascript array

I have the following array :
[
{ name: "iPhone 12", quantity: 12, price: 325, … },
{ name: "iPhone 12", quantity: 4, price: 325, … },
{ name: "iPhone 13", quantity: 2, price: 525, … },
{ name: "iPhone 12", quantity: 2, price: 325 },
{ name: "iPhone 13", quantity: 3, price: 525 },
{ name: "iPhone SE", quantity: 2, price: 59 }
]
And I want to sum the quantity properties of each object in order to have an array with distinct elements like this :
[
{ name: "iPhone 12", quantity: 18, price: 325 },
{ name: "iPhone 13", quantity: 5, price: 525 },
{ name: "iPhone SE", quantity: 2, price: 59 }
]
How can I do that?
Seems like a good task for Array.prototype.reduce
const data = [{
name: "iPhone 12",
quantity: 12,
price: 325,
},
{
name: "iPhone 12",
quantity: 4,
price: 325,
},
{
name: "iPhone 13",
quantity: 2,
price: 525,
},
{
name: "iPhone 12",
quantity: 2,
price: 325
},
{
name: "iPhone 13",
quantity: 3,
price: 525
},
]
const summed = data.reduce((sum, current) => {
const item = sum.find(el => el.name === current.name)
if (item) {
for (const key in item) {
if (key === 'name') continue
item[key] += current[key]
}
} else {
sum.push({ ...current })
}
return sum
}, [])
console.log(summed)

Reformat Array of objects using array.map

I receive the result of an API call with the following array, I am trying to reformat this Array from:
const items = [
{
id: 1,
name: "Item 1",
section: { name: "Section A" }
},
{
id: 2,
name: "Item 2",
section: { name: "Section A" }
},
{
id: 3,
name: "Item 3",
section: { name: "Section A" }
},
{
id: 4,
name: "Item 4",
section: { name: "Section B" }
},
{
id: 5,
name: "Item 5",
section: { name: "Section B" }
},
{
id: 6,
name: "Item 6",
section: { name: "Section C" }
},
{
id: 7,
name: "Item 7",
section: { name: "Section C" }
}
];
To Array this:
const items = [
{
section: "Section A",
items: [
{
id: 1,
item: "Item 1"
},
{
id: 2,
item: "Item 2"
},
{
id: 3,
item: "Item 3"
}]
},
{
section: "Section B",
items: [
{
id: 4,
item: "Item 4"
},
{
id: 5,
item: "Item 5"
}]
},
{
section: "Section C",
items: [
{
id: 6,
item: "Item 6"
},
{
id: 7,
item: "Item 7"
}]
},
]
I have tried the following function:
const result = Array.from(new Set(items.map(s => s.section.name)))
.map(section => {
return {
section: section,
items: Array.from(new Set(items.map(function (item) {
if (item.section.name === section) {
return item.name
}
}
)))
}
})
This gives me the following result, which is close but I am not sure why I am getting the undefined values?
//[{section: "Section A", items: ["Item 1", "Item 2", "Item 3", undefined]},{section: "Section B", items:[undefined, "Item 4", "Item 5"]},{section: "Section C", items: [undefined, "Item 6", "Item 7"]}]
Can anyone assist me to correct this function or suggest a better approach?
You could take an object for grouping and get the values as result.
const
items = [{ id: 1, name: "Item 1", section: { name: "Section A" } }, { id: 2, name: "Item 2", section: { name: "Section A" } }, { id: 3, name: "Item 3", section: { name: "Section A" } }, { id: 4, name: "Item 4", section: { name: "Section B" } }, { id: 5, name: "Item 5", section: { name: "Section B" } }, { id: 6, name: "Item 6", section: { name: "Section C" } }, { id: 7, name: "Item 7", section: { name: "Section C" } }],
result = Object.values(items.reduce((r, { section: { name: section }, ...item }) => {
if (!r[section]) r[section] = { section, items: [] };
r[section].items.push(item);
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array prototype methods reduce() and findIndex()
like this:
const items = [
{
id: 1,
name: "Item 1",
section: { name: "Section A" }
},
{
id: 2,
name: "Item 2",
section: { name: "Section A" }
},
{
id: 3,
name: "Item 3",
section: { name: "Section A" }
},
{
id: 4,
name: "Item 4",
section: { name: "Section B" }
},
{
id: 5,
name: "Item 5",
section: { name: "Section B" }
},
{
id: 6,
name: "Item 6",
section: { name: "Section C" }
},
{
id: 7,
name: "Item 7",
section: { name: "Section C" }
}
];
const res = items.reduce((acc, curr) => {
const index = acc && acc.findIndex(({ section }) => section === curr.section.name)
if(index !== -1) {
acc[index].items.push({ id: curr.id, item: curr.name });
}
else {
acc.push({section: curr.section.name, items: [{ id: curr.id, item: curr.name }]});
}
return acc;
}, []);
console.log(res);

Dynamically created table - Vanilla Javascript only - not displaying in browser

I have a function that goes through and sorts items and their quantity and is supposed to display them in a table.
Nothing is appearing in the DOM or browser. Am I calling the function wrong or something?
I have an index.html file linked to my index.js file using a script.
There are no errors showing in chrome dev tools.
INSTRUCTION
Display the shelf and item pairings by calling the following
function displayShelfItemPair(shelfName, itemName);
function main() {
let yesterdaysOrders = [
{
id: 1,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 02",
quantity: 3
},
{
itemName: "Item 03",
quantity: 25
},
{
itemName: "Item 04",
quantity: 12
},
],
},
{
id: 2,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 08",
quantity: 42
},
{
itemName: "Item 09",
quantity: 13
},
{
itemName: "Item 12",
quantity: 37
},
],
},
{
id: 3,
orderLines: [{
itemName: "Item 12",
quantity: 16
}, ],
},
{
id: 4,
orderLines: [{
itemName: "Item 10",
quantity: 11
},
{
itemName: "Item 11",
quantity: 10
},
],
},
{
id: 5,
orderLines: [{
itemName: "Item 06",
quantity: 7
},
{
itemName: "Item 07",
quantity: 2
},
{
itemName: "Item 12",
quantity: 14
},
],
},
{
id: 6,
orderLines: [{
itemName: "Item 05",
quantity: 17
}, ],
},
{
id: 7,
orderLines: [{
itemName: "Item 03",
quantity: 5
},
{
itemName: "Item 07",
quantity: 2
},
],
},
{
id: 8,
orderLines: [{
itemName: "Item 02",
quantity: 13
},
{
itemName: "Item 07",
quantity: 7
},
{
itemName: "Item 09",
quantity: 2
},
],
},
{
id: 9,
orderLines: [{
itemName: "Item 01",
quantity: 4
},
{
itemName: "Item 06",
quantity: 17
},
{
itemName: "Item 07",
quantity: 3
},
],
},
{
id: 10,
orderLines: [{
itemName: "Item 11",
quantity: 12
},
{
itemName: "Item 12",
quantity: 1
},
],
}
],
result = Array.from(
yesterdaysOrders.reduce((acc, {
orderLines
}) => {
orderLines.forEach(({
itemName,
quantity
}) => acc.set(itemName, (acc.get(itemName) || 0) + quantity));
return acc;
}, new Map), ([itemName, quantity]) => ({
itemName,
quantity
}));
result.sort((a, b) => {
if (a.quantity > b.quantity) {
return -1;
} else if (a.quantity < b.quantity) {
return 1;
} else {
return 0;
}
});
function displayShelfItemPair(shelfName, itemName) {
let table = document.createElement('table');
document.body.appendChild(table);
for (let r in row) {
let tr = document.createElement('tr');
table.appendChild(tr); // Append to <table> node
for (let c in cell) {
let tdElement = document.createElement('td');
tdElement.innerHTML = result[i][j];
tr.appendChild(tdElement);
}
}
console.log(displayShelfItemPair(shelfName, itemName));
}
}
main();
DESIRED OUTPUT
ShelfName | itemName (w/quantity)
1 Item 12: 68
2 ''
'' ''
'' ''
You were iterating through objects that did not exist. For instance, for (let r in row) there is no row. I rewrote the function to hopefully get you closer.
function main() {
let yesterdaysOrders = [
{
id: 1,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 02",
quantity: 3
},
{
itemName: "Item 03",
quantity: 25
},
{
itemName: "Item 04",
quantity: 12
},
],
},
{
id: 2,
orderLines: [{
itemName: "Item 01",
quantity: 1
},
{
itemName: "Item 08",
quantity: 42
},
{
itemName: "Item 09",
quantity: 13
},
{
itemName: "Item 12",
quantity: 37
},
],
},
{
id: 3,
orderLines: [{
itemName: "Item 12",
quantity: 16
}, ],
},
{
id: 4,
orderLines: [{
itemName: "Item 10",
quantity: 11
},
{
itemName: "Item 11",
quantity: 10
},
],
},
{
id: 5,
orderLines: [{
itemName: "Item 06",
quantity: 7
},
{
itemName: "Item 07",
quantity: 2
},
{
itemName: "Item 12",
quantity: 14
},
],
},
{
id: 6,
orderLines: [{
itemName: "Item 05",
quantity: 17
}, ],
},
{
id: 7,
orderLines: [{
itemName: "Item 03",
quantity: 5
},
{
itemName: "Item 07",
quantity: 2
},
],
},
{
id: 8,
orderLines: [{
itemName: "Item 02",
quantity: 13
},
{
itemName: "Item 07",
quantity: 7
},
{
itemName: "Item 09",
quantity: 2
},
],
},
{
id: 9,
orderLines: [{
itemName: "Item 01",
quantity: 4
},
{
itemName: "Item 06",
quantity: 17
},
{
itemName: "Item 07",
quantity: 3
},
],
},
{
id: 10,
orderLines: [{
itemName: "Item 11",
quantity: 12
},
{
itemName: "Item 12",
quantity: 1
},
],
}
],
result = Array.from(
yesterdaysOrders.reduce((acc, {
orderLines
}) => {
orderLines.forEach(({
itemName,
quantity
}) => acc.set(itemName, (acc.get(itemName) || 0) + quantity));
return acc;
}, new Map), ([itemName, quantity]) => ({
itemName,
quantity
}));
result.sort((a, b) => {
if (a.quantity > b.quantity) {
return -1;
} else if (a.quantity < b.quantity) {
return 1;
} else {
return 0;
}
});
function displayShelfItemPairs() {
let table = document.createElement('table');
document.body.appendChild(table);
table.innerHTML = "<tr><th>ShelfName</th><th>itemName (w/quantity)</th></tr>"
let shelf = 1;
for (let r of result) {
let tr = document.createElement('tr');
table.appendChild(tr); // Append to <table> node
tr.innerHTML = "<td>" + shelf + "</td><td>" + r.itemName + ": " + r.quantity + "</td>";
shelf++
}
}
displayShelfItemPairs()
}
main();
Edit: As I now figured out, output will be the same regardless whether you append children before or after filling them.
In your function displayShelfItemPair, you are appending the new table element before filling it, which is why is displays nothing on the page.
Fill the table element with rows, etc., and then append it to the document:
function displayShelfItemPair(shelfName, itemName) {
let table = document.createElement('table');
for (let i = 0; i < 3; i++) {
let tr = document.createElement('tr');
for (let j = 0; j < 3; j++) {
let tdElement = document.createElement('td');
tdElement.innerHTML = result[i][j];
tr.appendChild(tdElement);
}
table.appendChild(tr); // Append to <table> node AFTER it is filled
}
document.body.appendChild(table); //append table to body AFTER it is filled
console.log(displayShelfItemPair(shelfName, itemName));
}

Sorting values in array of objects within array of objects

I'd like to sort through all the itemNames and add all the appropriate quantities together to be able to determine which items were ordered the most.
Here is the array of objects below. I want to try to filter and map through the array of objects and list out the itemName and appropriate totaled quantity for each one, just not sure how to chain together.
function OrderRepository() {
return orderLines.filter((itemName) => {
orderLines.map((quantity) => {
return
}
}
}
Provided array of objects
OrderRepository.prototype.getYesterdaysOrders = function getYesterdaysOrders() {
var yesterdaysOrders = [
{
id: 1,
orderLines: [
{ itemName: "Item 01", quantity: 1 },
{ itemName: "Item 02", quantity: 3 },
{ itemName: "Item 03", quantity: 25 },
{ itemName: "Item 04", quantity: 12 },
],
},
{
id: 2,
orderLines: [
{ itemName: "Item 01", quantity: 1 },
{ itemName: "Item 08", quantity: 42 },
{ itemName: "Item 09", quantity: 13 },
{ itemName: "Item 12", quantity: 37 },
],
},
{
id: 3,
orderLines: [
{ itemName: "Item 12", quantity: 16 },
],
},
{
id: 4,
orderLines: [
{ itemName: "Item 10", quantity: 11 },
{ itemName: "Item 11", quantity: 10 },
],
},
{
id: 5,
orderLines: [
{ itemName: "Item 06", quantity: 7 },
{ itemName: "Item 07", quantity: 2 },
{ itemName: "Item 12", quantity: 14 },
],
},
{
id: 6,
orderLines: [
{ itemName: "Item 05", quantity: 17 },
],
},
{
id: 7,
orderLines: [
{ itemName: "Item 03", quantity: 5 },
{ itemName: "Item 07", quantity: 2 },
],
},
{
id: 8,
orderLines: [
{ itemName: "Item 02", quantity: 13 },
{ itemName: "Item 07", quantity: 7 },
{ itemName: "Item 09", quantity: 2 },
],
},
{
id: 9,
orderLines: [
{ itemName: "Item 01", quantity: 4 },
{ itemName: "Item 06", quantity: 17 },
{ itemName: "Item 07", quantity: 3 },
],
},
{
id: 10,
orderLines: [
{ itemName: "Item 11", quantity: 12 },
{ itemName: "Item 12", quantity: 1 },
],
},
];
return yesterdaysOrders;
};
Desired result
{ itemName: "Item 01", quantity: 6 }
{ itemName: "Item 02", ...... }
I'd like the itemName in order with the totaled quantity listed for that item. So the total number of times Item 01 was ordered yesterday was 6.
You could count the items with the help of a Map and render the wanted result as an array.
var data = [{ id: 1, orderLines: [{ itemName: "Item 01", quantity: 1 }, { itemName: "Item 02", quantity: 3 }, { itemName: "Item 03", quantity: 25 }, { itemName: "Item 04", quantity: 12 }] }, { id: 2, orderLines: [{ itemName: "Item 01", quantity: 1 }, { itemName: "Item 08", quantity: 42 }, { itemName: "Item 09", quantity: 13 }, { itemName: "Item 12", quantity: 37 }] }, { id: 3, orderLines: [{ itemName: "Item 12", quantity: 16 }] }, { id: 4, orderLines: [{ itemName: "Item 10", quantity: 11 }, { itemName: "Item 11", quantity: 10 }] }, { id: 5, orderLines: [{ itemName: "Item 06", quantity: 7 }, { itemName: "Item 07", quantity: 2 }, { itemName: "Item 12", quantity: 14 }] }, { id: 6, orderLines: [{ itemName: "Item 05", quantity: 17 }] }, { id: 7, orderLines: [{ itemName: "Item 03", quantity: 5 }, { itemName: "Item 07", quantity: 2 }] }, { id: 8, orderLines: [{ itemName: "Item 02", quantity: 13 }, { itemName: "Item 07", quantity: 7 }, { itemName: "Item 09", quantity: 2 }] }, { id: 9, orderLines: [{ itemName: "Item 01", quantity: 4 }, { itemName: "Item 06", quantity: 17 }, { itemName: "Item 07", quantity: 3 }] }, { id: 10, orderLines: [{ itemName: "Item 11", quantity: 12 }, { itemName: "Item 12", quantity: 1 }] }],
result = Array.from(
data.reduce((m, { orderLines }) => {
orderLines.forEach(({ itemName, quantity }) => m.set(itemName, (m.get(itemName) || 0) + quantity));
return m;
}, new Map),
([itemName, quantity]) => ({ itemName, quantity })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is what you are looking for:
var hashmap = {}
for(var each of yesterdaysOrders) {
for(var one of each['orderLines']) {
if (one['itemName'] in hashmap) {
hashmap[one['itemName']] += one['quantity']
} else {
hashmap[one['itemName']] = one['quantity']
}
}
}
You can use JavaScript's reduce() method to do that.
let result = yesterdaysOrders.reduce((arr, currentValue) => {
currentValue.orderLines.forEach(order => {
const index = arr.findIndex(item => item.itemName === order.itemName);
if (index === -1) {
arr.push(order);
} else {
arr[index].quantity += order.quantity;
}
});
return arr;
}, []);
And sort the resultant array using Array.sort().
// Sorting on item name in ascending order.
result.sort((a, b) => {
if (a.itemName < b.itemName) {
return -1;
} else if (a.itemName > b.itemName) {
return 1;
} else {
return 0;
}
});
Demo:
var yesterdaysOrders = [
{
id: 1,
orderLines: [
{ itemName: "Item 01", quantity: 1 },
{ itemName: "Item 02", quantity: 3 },
{ itemName: "Item 03", quantity: 25 },
{ itemName: "Item 04", quantity: 12 },
],
},
{
id: 2,
orderLines: [
{ itemName: "Item 01", quantity: 1 },
{ itemName: "Item 08", quantity: 42 },
{ itemName: "Item 09", quantity: 13 },
{ itemName: "Item 12", quantity: 37 },
],
},
{
id: 3,
orderLines: [
{ itemName: "Item 12", quantity: 16 },
],
},
{
id: 4,
orderLines: [
{ itemName: "Item 10", quantity: 11 },
{ itemName: "Item 11", quantity: 10 },
],
},
{
id: 5,
orderLines: [
{ itemName: "Item 06", quantity: 7 },
{ itemName: "Item 07", quantity: 2 },
{ itemName: "Item 12", quantity: 14 },
],
},
{
id: 6,
orderLines: [
{ itemName: "Item 05", quantity: 17 },
],
},
{
id: 7,
orderLines: [
{ itemName: "Item 03", quantity: 5 },
{ itemName: "Item 07", quantity: 2 },
],
},
{
id: 8,
orderLines: [
{ itemName: "Item 02", quantity: 13 },
{ itemName: "Item 07", quantity: 7 },
{ itemName: "Item 09", quantity: 2 },
],
},
{
id: 9,
orderLines: [
{ itemName: "Item 01", quantity: 4 },
{ itemName: "Item 06", quantity: 17 },
{ itemName: "Item 07", quantity: 3 },
],
},
{
id: 10,
orderLines: [
{ itemName: "Item 11", quantity: 12 },
{ itemName: "Item 12", quantity: 1 },
],
},
];
let result = yesterdaysOrders.reduce((arr, currentValue) => {
currentValue.orderLines.forEach(order => {
const index = arr.findIndex(item => item.itemName === order.itemName);
if (index === -1) {
arr.push(order);
} else {
arr[index].quantity += order.quantity;
}
});
return arr;
}, []);
// Sorting on item name in ascending order.
result.sort((a, b) => {
if (a.itemName < b.itemName) {
return -1;
} else if (a.itemName > b.itemName) {
return 1;
} else {
return 0;
}
});
console.log(result);

kendoTreeList - aggregate not working properly

Please help me, I am stuck with aggregates for kendoTreeList -
I create kendoTreeList, but failed to calculate sum for groups.
$(document).ready(function () {
var _jsondata = [
{ ID: 1, Name: "Parent 1", Amount: "200", parentId: null },
{ ID: 2, Name: "Parent 2", Amount: "500", parentId: null },
{ ID: 11, Name: "Child 11", Amount: "50", parentId: 1 },
{ ID: 12, Name: "Child 12", Amount: "150", parentId: 1 },
{ ID: 21, Name: "Child 21", Amount: "100", parentId: 2 },
{ ID: 22, Name: "Child 22", Amount: "200", parentId: 2 },
{ ID: 23, Name: "Child 23", Amount: "200", parentId: 2 }
];
var dataSource = new kendo.data.TreeListDataSource({
data : _jsondata,
schema : { model: { id: "ID", expanded: true }},
aggregate : [
{ field: "Amount", aggregate: "sum"}
]
});
$("#treelist").kendoTreeList({
dataSource : dataSource,
columns : [
{ field: "Name" , nullable: false },
{ field: "Amount", footerTemplate: "#= sum #"}
]
});
});
this give result as -
Since Amount represented in _jsondata as string, you need to define it in schema.model as number
schema: {
model: {
id: "ID",
expanded: true,
fields: {
Amount: { type: 'number' }
}
}
},

Categories