Normalizing State Shape #1
Description:
Normalizing State Shape Part 1
In web application development, managing state is crucial, especially when dealing with complex data structures. In this kata, you'll be tasked with normalizing the state of a blog application, specifically focusing on blog posts, comments, and users.
The input data represents a collection of blog posts with associated authors and comments. Your goal is to transform this data into a normalized state object, following the principles of database design.
To achieve this, you need to create a function called normalizeState(blogPosts)
, where blogPosts
is an array of objects representing the blog posts.
Input
The input data blogPosts
looks like this:
[
{
id: String,
author: {
username: String,
name: String,
},
body: String,
comments: [
{
id: String,
author: {
username: String,
name: String,
},
comment: String,
},
// Repeat for more comments
],
},
// Repeat for more blog posts
]
The
blogPosts
array will always be provided as a valid array of objects representing blog posts.Each blog post object will have the properties
id
(string),author
(object),body
(string), andcomments
(array).The
author
property in each blog post object will have the propertiesusername
(string) andname
(string).The
comments
property in each blog post object will be an array of objects representing comments.The
comments
array can be an empty array.Each comment object will have the properties
id
(string),author
(object), andcomment
(string).The
author
property in each comment object will have the propertiesusername
(string) andname
(string).The
username
property in the author objects will be unique across the entireblogPosts
array.The
id
property in the blog post objects and the comment objects will be unique across the entireblogPosts
array.
Output
The function should return a normalized state object according to the following schema:
{
entities: {
authors: {
byId: {
[username: String]: {
username: String,
name: String,
},
},
allIds: [String],
},
posts: {
byId: {
[postId: String]: {
id: String,
author: String,
body: String,
comments: [String],
},
},
allIds: [String],
},
comments: {
byId: {
[commentId: String]: {
id: String,
author: String,
comment: String,
},
},
allIds: [String],
},
authorPosts: {
byId: {
[username: String]: [String],
},
allIds: [String],
},
},
}
The
authors
object represents all authors (posts and comments).Each blog post should be represented as an object in the
posts
object, using the post'sid
as the key. Each post object should have the propertiesid
,author
,body
, andcomments
.The
author
property in the post object should be a string representing the author'susername
.The
comments
property in the post object should be an array of comment IDs associated with that post.Each comment should be represented as an object in the
comments
object, using the comment'sid
as the key. Each comment object should have the propertiesid
,author
, andcomment
.The
author
property in the comment object should be a string representing the author'susername
.The
authorPosts
object should represent the relationship between authors and posts. TheauthorPosts
object has two properties:byId
: An object where each key is an author's username and the corresponding value is an array of post IDs authored by that user.allIds
: An array containing all the usernames of authors.
The
allIds
arrays in each object should contain the IDs of the respective entities in the same order as they appear.The
byId
objects can be ordered how you like. The ordering doesn't matter.
Example
Input:
const blogPosts = [
{
id: "post1",
author: { username: "user1", name: "User 1" },
body: "......",
comments: [
{
id: "comment1",
author: { username: "user2", name: "User 2" },
comment: ".....",
},
],
},
{
id: "post2",
author: { username: "user2", name: "User 2" },
body: "......",
comments: [],
},
{
id: "post3",
author: { username: "user3", name: "User 3" },
body: "......",
comments: [
{
id: "comment2",
author: { username: "user1", name: "User 1" },
comment: ".....",
},
{
id: "comment3",
author: { username: "user3", name: "User 3" },
comment: ".....",
},
],
},
]
Output:
{
entities: {
authors: {
byId: {
user1: { username: "user1", name: "User 1" },
user2: { username: "user2", name: "User 2" },
user3: { username: "user3", name: "User 3" },
},
allIds: ["user1", "user2", "user3"],
},
posts: {
byId: {
post1: {
id: "post1",
author: "user1",
body: "......",
comments: ["comment1"],
},
post2: {
id: "post2",
author: "user2",
body: "......",
comments: [],
},
post3: {
id: "post3",
author: "user3",
body: "......",
comments: ["comment2", "comment3"],
},
},
allIds: ["post1", "post2", "post3"],
},
comments: {
byId: {
comment1: {
id: "comment1",
author: "user2",
comment: ".....",
},
comment2: {
id: "comment2",
author: "user1",
comment: ".....",
},
comment3: {
id: "comment3",
author: "user3",
comment: ".....",
},
},
allIds: ["comment1", "comment2", "comment3"],
},
authorPosts: {
byId: {
user1: ["post1"],
user2: ["post2"],
user3: ["post3"],
},
allIds: ["user1", "user2", "user3"],
},
},
}
By organizing the state in this normalized structure, we can easily access and update specific entities and establish relationships between them. It provides efficient data retrieval and avoids data duplication, resulting in a more manageable and scalable state management solution.
In Part 2 (coming soon) we will be looking at CRUD operations on the normalized state.
Similar Kata:
Stats:
Created | Jun 9, 2023 |
Published | Jun 9, 2023 |
Warriors Trained | 85 |
Total Skips | 42 |
Total Code Submissions | 150 |
Total Times Completed | 13 |
JavaScript Completions | 13 |
Total Stars | 2 |
% of votes with a positive feedback rating | 83% of 9 |
Total "Very Satisfied" Votes | 7 |
Total "Somewhat Satisfied" Votes | 1 |
Total "Not Satisfied" Votes | 1 |
Total Rank Assessments | 9 |
Average Assessed Rank | 5 kyu |
Highest Assessed Rank | 4 kyu |
Lowest Assessed Rank | 7 kyu |