Issue
I have an array of content blocks like so:
interface Content{
type: string,
content: string | string[]
}
const content: Content[] = [
{
type: "heading"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "heading"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "list_item"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
]
I'm trying to write a function which can merge these list_item
's into a list
with an array for the content of each. So, the output of the function for the above input should be:
[
{
type: "heading"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "list"
content: ["whatever","whatever","whatever"]
},
{
type: "para"
content: "whatever"
},
{
type: "heading"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "para"
content: "whatever"
},
{
type: "list"
content: ["whatever", "whatever", "whatever", "whatever"]
},
{
type: "para"
content: "whatever"
},
]
I've been trying to use a three-pointer system, looping over the array from i=1 to i < length - 1, tracking the prev
, curr
and next
blocks, however, I am getting very stuck with the logic and how I should handle the cases.
I feel like this is quite a simple problem for more experienced algorithm designers, so, I was looking for some guidance.
Solution
A fairly straightforward loop, checking if the current.type
is a 'list_item' and either instantiating a new object with type: 'list'
or pushing to the previous object if we've already created one.
const content = [{ type: "heading", content: "whatever" }, { type: "para", content: "whatever" }, { type: "para", content: "whatever" }, { type: "list_item", content: "list1 1" }, { type: "list_item", content: "list1 2" }, { type: "list_item", content: "list1 3" }, { type: "para", content: "whatever" }, { type: "heading", content: "whatever" }, { type: "para", content: "whatever" }, { type: "para", content: "whatever" }, { type: "list_item", content: "list2 1" }, { type: "list_item", content: "list2 2" }, { type: "list_item", content: "list2 3" }, { type: "list_item", content: "list2 4" }, { type: "para", content: "whatever" },];
const res = [];
for (const item of content) {
if (item.type === 'list_item') {
if (res[res.length - 1]?.type !== 'list') {
res.push({ type: 'list', content: [] });
}
res[res.length - 1].content.push(item.content);
} else {
res.push({ ...item });
}
}
console.log(res);
An alternative that avoids having to repeatedly access the tail of the array is to store a reference to the active list array in a temp variable and reset it every time a sequence of list_item
s ends. (TSPlayground)
const content = [{ type: "heading", content: "whatever" }, { type: "para", content: "whatever" }, { type: "para", content: "whatever" }, { type: "list_item", content: "list1 1" }, { type: "list_item", content: "list1 2" }, { type: "list_item", content: "list1 3" }, { type: "para", content: "whatever" }, { type: "heading", content: "whatever" }, { type: "para", content: "whatever" }, { type: "para", content: "whatever" }, { type: "list_item", content: "list2 1" }, { type: "list_item", content: "list2 2" }, { type: "list_item", content: "list2 3" }, { type: "list_item", content: "list2 4" }, { type: "para", content: "whatever" },];
const res = [];
let temp = [];
for (const item of content) {
if (item.type === 'list_item') {
if (!temp.length) {
res.push({ type: 'list', content: temp });
}
temp.push(item.content);
} else {
if (temp.length) {
temp = [];
}
res.push({ ...item });
}
}
console.log(res);
Answered By - pilchard
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.