1

I have a piece of code here, and i wanted to identify the last element paragraph 3 and add some text like - last item and the output would be paragraph 3 - last item.

I would prefer if its recursive since there is no limit on the number children in an object.

obj = {
    content: [
        { text: "paragraph 1" },
        { 
            content: [
                { text: "paragraph 2" },
            ]
        },
        { text: "paragraph 3" },
    ]
}

Another example would be this, its output should be paragraph 5 - last item

obj = {
    content: [
        { text: "paragraph 1" },
        { 
            content: [
                { text: "paragraph 2" }
            ]
        },
        { text: "paragraph 3" },
        { 
            content: [
                { text: "paragraph 4" },
                { 
                    content: [
                        { text: "paragraph 5" }
                    ]
                }
            ]
        }
    ]
}
1
  • Define a recursive iteration function, function recur(content = []) { return content.map(Object.entries).map(([key, value]) => key === “text" ? [value] : key === "content" ? value.map(r) : []).flat(); }, then invoke it as in recur(obj.content).sort((x, y) => x.localeCompare(y))[0] + “ - last" Commented Nov 14, 2021 at 5:41

4 Answers 4

4

A simple implementation. Checks the key name and if it's content, it'll recall itself with the last element. Else, it'll return it.

const obj1 = {
  content: [{
    text: "paragraph 1"
  }, {
    content: [{
      text: "paragraph 2"
    }]
  }, {
    text: "paragraph 3"
  }]
};

const obj2 = {
  content: [{
      text: "paragraph 1"
    },
    {
      content: [{
        text: "paragraph 2"
      }]
    }, {
      text: "paragraph 3"
    },
    {
      content: [{
          text: "paragraph 4"
        },
        {
          content: [{
            text: "paragraph 5"
          }]
        }
      ]
    }
  ]
}

function getLatestParagraph(obj) {
  for (const key in obj) {
    if (key === "content") return getLatestParagraph(obj[key].pop());
    return obj[key];
  }
}

console.log(getLatestParagraph(obj1))
console.log(getLatestParagraph(obj2))

Sign up to request clarification or add additional context in comments.

Comments

2

One way is to loop and get a reference to text in one variable and update it each loop. After all the loops end the variable will be pointing to tha last text so you just add ' - last item' to it.

Here is a working example:

const obj1 = {
  content: [{
      text: 'paragraph 1'
    },
    {
      content: [{
        text: 'paragraph 2'
      }]
    },
    {
      text: 'paragraph 3'
    },
    {
      content: [{
          text: 'paragraph 4'
        },
        {
          content: [{
            text: 'paragraph 5'
          }]
        },
      ],
    },
  ],
}

const obj2 = {
  content: [{
      text: 'paragraph 1'
    },
    {
      content: [{
        text: 'paragraph 2'
      }]
    },
    {
      text: 'paragraph 3'
    },
  ],
}

let last

function getLast(o) {
  for (let key in o) {
    if (o[key] instanceof Array) {
      for (let value of o[key]) {
        getLast(value)
      }
    } else if (key == 'text') {
      last = o
    }
  }
}

getLast(obj1)
last.text += ' - last item'
getLast(obj2)
last.text += ' - last item'

console.log('\nobj1 = ', JSON.stringify(obj1, null, 1))
console.log('\nobj2 = ', JSON.stringify(obj2, null, 1))

Edit: If what you actually wanted is just get the text of the last item then you can also do this:

const obj1 = {
  content: [{
      text: 'paragraph 1'
    },
    {
      content: [{
        text: 'paragraph 2'
      }]
    },
    {
      text: 'paragraph 3'
    },
    {
      content: [{
          text: 'paragraph 4'
        },
        {
          content: [{
            text: 'paragraph 5'
          }]
        },
      ],
    },
  ],
}

const obj2 = {
  content: [{
      text: 'paragraph 1'
    },
    {
      content: [{
        text: 'paragraph 2'
      }]
    },
    {
      text: 'paragraph 3'
    },
  ],
}


let last
function getLast(o) {
  for (let key in o) {
    if (o[key] instanceof Array) {
      for (let value of o[key]) {
        getLast(value)
      }
    } else if (key == 'text') {
      last = o
    }
  }
  return last.text
}

const last1 = getLast(obj1)
console.log(last1)
const last2 = getLast(obj2)
console.log(last2)

Comments

2

This is a recursive solution that takes the last item in content, as long as there's one, or just returns the current object's text:

const obj1 = {"content":[{"text":"paragraph 1"},{"content":[{"text":"paragraph 2"}]},{"text":"paragraph 3"}]};
const obj2 = {"content":[{"text":"paragraph 1"},{"content":[{"text":"paragraph 2"}]},{"text":"paragraph 3"},{"content":[{"text":"paragraph 4"},{"content":[{"text":"paragraph 5"}]}]}]}

const getLatestParagraph = obj => 
  !obj.content?.at(-1) // if there isn't a last item in content
  ? obj.text // return the current text
  : getLatestParagraph(obj.content.at(-1)) // or run the function on the new last item

console.log(getLatestParagraph(obj1))
console.log(getLatestParagraph(obj2))

Comments

1

You can map on the content property and return each element. If the content property exists, same condition will run again, else it will print the text property.

let lastItem = {};

function recursive(node) {
    if (node.content) {
        node.content.map(element => recursive(element));
    } else if (node.text) {
        lastItem = node.text;
    }
}

obj.content.map(node => recursive(node));
console.log(lastItem + " - last item");

Working demo: https://jsfiddle.net/4f7Lt3ue/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.