This is awesome! I learn so many collateral concepts when you cover basic topics. With this video, you cover both more advanced topics and work through programming approaches to problems. This has to be the most under-appreciated channel on TH-cam. Thank you Steve!
For the first part I do have a more dynamic solution. Instead of a switch, there are an approved list of statuses. Then the function uses the start list, to create groupes - that don't exist and add new books to the existing ones. let start = []//Array of objects. let approved = ['completed', 'in-progress', 'not-started'], //Switches all = false; //Change this one to true, if you want to output all the groups that are found in the start Array. start.reduce((acc, obj) => { let status = obj.status, //checking if there is a group by that status idx = acc.findIndex(e => e.status === status); //new book obj, that can later be added where it belongs book = {'id':obj.id,'name':obj.name}; //if group don't exist create new one idx === -1 //if flag all or approved switch are correct ? (all || approved.includes(status)) ? //adds new status object or leaves the current obj by null acc = [...acc, {'status':status, 'books':[book]}] : null //adds new book to the books key list : acc[idx].books = [...acc[idx].books, book] //updates accumulator, by returning it return acc; }, []); //initiate with empty Array instead of a predefined one.
Right now there is a chrome(101) trail started, under a flag. It's two grouping functions, Array.prototype methods groupBy() and groupByToMap(), that will be added to JavaScript core..
Hey! This helped me through the bulk of a problem! Thanks a ton! I did have one question. Say you are dealing with data that instead of status has Ids. If you had to process a high volume of data without knowing what the ids would be in advance how would you go about setting up the initial values in the accumulator?
If you didn't know what the IDs would be like, you would need to use some conditionals to figure that out before hand. A bit verbose, but without a concrete example, that would be my initial suggestion.
can you explain this code pls : i try with : bk1.id < bk2.id ? -1 : 1 but this not work. final.map((obj) => obj.books.sort( (bk1, bk2) => bk1.name.toString().toLowerCase() < bk2.name.toString().toLowerCase() ? -1 : 1 ) )
This is awesome! I learn so many collateral concepts when you cover basic topics. With this video, you cover both more advanced topics and work through programming approaches to problems. This has to be the most under-appreciated channel on TH-cam. Thank you Steve!
Glad it was helpful!
For the first part I do have a more dynamic solution. Instead of a switch, there are an approved list of statuses.
Then the function uses the start list, to create groupes - that don't exist and add new books to the existing ones.
let start = []//Array of objects.
let approved = ['completed', 'in-progress', 'not-started'], //Switches
all = false; //Change this one to true, if you want to output all the groups that are found in the start Array.
start.reduce((acc, obj) => {
let status = obj.status,
//checking if there is a group by that status
idx = acc.findIndex(e => e.status === status);
//new book obj, that can later be added where it belongs
book = {'id':obj.id,'name':obj.name};
//if group don't exist create new one
idx === -1
//if flag all or approved switch are correct
? (all || approved.includes(status)) ?
//adds new status object or leaves the current obj by null
acc = [...acc, {'status':status, 'books':[book]}] : null
//adds new book to the books key list
: acc[idx].books = [...acc[idx].books, book]
//updates accumulator, by returning it
return acc;
}, []); //initiate with empty Array instead of a predefined one.
Love it! Thanks for sharing!
great to see you posting!
Grouping and Sorting in JavaScript, beautifully explained. Thanks,
{2022-04-15}
Right now there is a chrome(101) trail started, under a flag. It's two grouping functions, Array.prototype methods groupBy() and groupByToMap(), that will be added to JavaScript core..
Perfect
Debanubce and throttle please ...
Hey! This helped me through the bulk of a problem! Thanks a ton! I did have one question. Say you are dealing with data that instead of status has Ids. If you had to process a high volume of data without knowing what the ids would be in advance how would you go about setting up the initial values in the accumulator?
If you didn't know what the IDs would be like, you would need to use some conditionals to figure that out before hand. A bit verbose, but without a concrete example, that would be my initial suggestion.
i am waiting for this..🙈🙈. thanks for this tutorial
You're welcome 😊
Why not replace 'map' by 'forEach' in line 59? 'map' method returns a new array which result you don't use.
Yes, agree. forEach would be more to the point here.
Great, thanks.
can you explain this code pls :
i try with : bk1.id < bk2.id
? -1 : 1
but this not work.
final.map((obj) =>
obj.books.sort(
(bk1, bk2) =>
bk1.name.toString().toLowerCase() < bk2.name.toString().toLowerCase() ?
-1 : 1
)
)
It looks like it is mapping a new array and then sorting each object in that array. What is the data in final?
The following solution reals with dynamic statuses:
let start = [
{ id: 1, status: 'completed', name: 'The Lord of the Rings' },
{ id: 2, status: 'in-progress', name: 'Lord of the Flies' },
{ id: 3, status: 'not-started', name: 'Dune' },
{ id: 4, status: 'not-started', name: 'American Gods' },
{ id: 5, status: 'completed', name: 'Ender\'s Game' },
{ id: 6, status: 'in-progress', name: 'Brave New World' },
{ id: 7, status: 'completed', name: '1984' },
];
let final = [];
let hashed = start.reduce( (acc, obj) => {
if (acc && !acc.hasOwnProperty(obj.status))
acc[obj.status] = [];
acc[obj.status].push({ id: obj.id, name: obj.name });
return acc;
}, {});
(Object.keys(hashed)).map( item => {
hashed[item].sort( (bk1, bk2) => { return ((bk1.name < bk2.name) ? -1 : 1); });
final.push( {status: item, books: hashed[item]} );
});
console.log(JSON.stringify(final, null, 4));
Thanks for sharing that solution!