0

In the below data structure,

data = {
  data: [{
    areas: [{
      sections: [{
          rjf: [{
            type: 'heading-1'
            text: 'Sample Heading',
          }]
        },
        {
          rjf: [{
              type: 'paragraph',
              depth: 0,
              text: 'This website is offered to you by:',
              inlineStyleRanges: [],
              inlineEntityRanges: []
            },
            {
              "type": "ordered-list-item",
              "text": "Ordered Item A",
            },
            {
              "type": "unordered-list-item",
              "text": "Ordered Item B",
            },
            {
              type: 'paragraph',
              depth: 0,
              text: 'This website is offered to you by:',
              inlineStyleRanges: [],
              inlineEntityRanges: []
            },
            {
              "type": "ordered-list-item",
              "text": "Ordered Item A",
            },
            {
              "type": "unordered-list-item",
              "text": "Ordered Item B",
            }
          ]
        }
      ]
    }]
  }]
};

I'm trying to group all the type which as ordered-list-item & unordered-list-item into new object. Something like below,

{
    "type": 'list',
    "items": [
      {
        "type": "ordered-list-item",
        "text": "Ordered Item A",
      },
      {
        "type": "unordered-list-item",
        "text": "Ordered Item B",
      }
    ]
  }

After so much treble, I came with the below solution. This works fine. But having an issue, In rjf if ordered-list-item & unordered-list-item not found nothing should be happen unfortunately and empty list getting added to rjf.

Below is the code snippet, please help me to fix this issue.

const data = {
  data: [{
    areas: [{
      sections: [{
          rjf: [{
            text: 'Sample Heading',
          }]
        },
        {
          rjf: [{
              type: 'paragraph',
              depth: 0,
              text: 'This website is offered to you by:',
              inlineStyleRanges: [],
              inlineEntityRanges: []
            },
            {
              "type": "ordered-list-item",
              "text": "Ordered Item A",
            },
            {
              "type": "unordered-list-item",
              "text": "Ordered Item B",
            },
            {
              type: 'paragraph',
              depth: 0,
              text: 'This website is offered to you by:',
              inlineStyleRanges: [],
              inlineEntityRanges: []
            },
            {
              "type": "ordered-list-item",
              "text": "Ordered Item A",
            },
            {
              "type": "unordered-list-item",
              "text": "Ordered Item B",
            }
          ]
        }
      ]
    }]
  }]
};
const moveToNewObject = (data) => {
  const sections = data[0].areas[0].sections;
  sections.forEach(data => {
    let list = data.rjf;
    let a = list.map((entry, index) => {
      return { ...entry,
        index,
        use: entry.type !== 'unordered-list-item' && entry.type !== 'ordered-list-item'
      }
    }).filter(entry => entry.use).map((entry, index, entries) => {
      const end = index < entries.length - 1 ? entries[index + 1].index : list.length - entry.index;
      return [{
        type: entry.type,
        text: entry.text
      }, {
        type: 'list',
        items: list.slice(entry.index + 1, entry.index + end)
      }]
    });
    console.log(a);
  });
}
console.log(moveToNewObject(data.data));

0

2 Answers 2

1

Your data has a very weird structure which makes it harder to be honest. The snippet below uses a function that uses map on all your sections, and if rjf type is 'unordered-list-item' or 'ordered-list-item', it moves it to a new rjf of type list as items. Hopefully it's what you wanted.

And here's a fiddle if you want clearer code formatting: https://jsfiddle.net/qce2vLr3/

const data = {
  data: [
    {
      areas: [
        {
          sections: [
            {
              rjf: [
                {
                  text: 'Sample Heading',
                }
              ]
            },
            {
              rjf: [
                {
                  type: 'paragraph',
                  depth: 0,
                  text: 'This website is offered to you by:',
                  inlineStyleRanges: [],
                  inlineEntityRanges: []
                },
                {
                  "type": "ordered-list-item",
                  "text": "Ordered Item A",
                },
                {
                  "type": "unordered-list-item",
                  "text": "Ordered Item B",
                }
              ]
            }
          ]
        }
      ]
    }
  ]
};

const moveToNewObject = (data) => {
	const sections = data[0].areas[0].sections; // why is data an array?
  return sections.map((section) => {
  	if (section.rjf) {
    	const looseItems = section.rjf.filter((rjf) => rjf.type && ['ordered-list-item', 'unordered-list-item'].includes(rjf.type));
      if (looseItems.length) {
      	return { 
        	rjf: [
          	...section.rjf,
          	{ 
          		type: 'list',
            	items: looseItems 
          	}
          ].filter((rjf) => rjf.type && !['ordered-list-item', 'unordered-list-item'].includes(rjf.type))
        }
      }
      return section;
    }
    return section;
  })
}

data.data[0].areas[0].sections = moveToNewObject(data.data);
console.log(data.data);

UPDATE

Here's a solution that "groups" your lists by multiple headings: https://jsfiddle.net/pkLyd0gh/

const data = {
  data: [
    {
      areas: [
        {
          sections: [
            {
              rjf: [
                {
                  text: 'Sample Heading',
                }
              ]
            },
            {
              rjf: [
                {
                  "type": "heading-1",
                  "text": "A title",
                },
                {
                  "type": "ordered-list-item",
                  "text": "Ordered Item A",
                },
                {
                  "type": "unordered-list-item",
                  "text": "Ordered Item B",
                },
                {
                  "type": "heading-2",
                  "text": "A title",
                },
                {
                  "type": "ordered-list-item",
                  "text": "Ordered Item C",
                },
                {
                  "type": "unordered-list-item",
                  "text": "Ordered Item D",
                }
              ]
            }
          ]
        }
      ]
    }
  ]
};

const reformattedSections = (data) => {
	const sections = data[0].areas[0].sections;
  const listItemTypes = ['unordered-list-item', 'ordered-list-item'];
  return sections.map((section) => {
  	let lastHeadingIndex = -1;
  	return section.rjf.reduce((acc, current, index) => {
    	if (!current.type || !listItemTypes.includes(current.type)) {
      	lastHeadingIndex = acc.length;
        return [...acc, current]
      }
      else {
      	let listObject = acc.find((el, i) => i > lastHeadingIndex && i < index && el.type === 'list');
        if (!listObject) {
        	listObject = {
          	type: 'list',
            items: [current]
          }
          return [...acc, listObject];
        }
        listObject.items = [...listObject.items, current];
      	return acc;
      }
    }, [])
  })
}

data.data[0].areas[0].sections = reformattedSections(data.data);
console.log('sections', data.data);

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

9 Comments

Position of grouping ordered-list-item & unordered-list-item is not maintained. For example, after the list if I get a paragraph grouping should stop.
Can't understand, it only groups ordered-list-item & unordered-list-item into type list. Your new example shows that the results are doubled?
Its not doubled, I can have multiple list items and I wanted to maintain its position. I've updated the question with current & expected one
In current solutions which you provided, all list items are grouped at last. Expecting the output like this jsfiddle.net/2gjyrxkq
If I understand correctly you want your array to be structured with heading type being followed by it's contents (i.e. type list)? It is probably doable (use reduce instead of map plus array destructuring) but I would advice you against doing that. Introducing such logic makes code hard to maintain and unreadable. Array is not a proper data structure for this kind of thing, you'd better use an objects such as { heading: <your heading object>, contents: <i.e. your list> for this. If you get this input from your Backend, it's backend's job to provide it in readable format.
|
0

slice is a method on array's not on objects. DATA in your code is an Object

const a ={a:1,b:2,c:3,d:4}
const b =[1,2,3,4]

//console.log(a.slice(1,3)) //this will return the error    
console.log(b.slice(1,3))

Hope it helps.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.