Search code examples
javascriptecmascript-6javascript-objects

Create sub-arrays for adjacent objects with specific property


I'm currently trying to wrap my head around a piece of logic regarding JS array methods.

Looking at an array of objects, how can I group adjacent items with a specific value, by creating an new object, containing a sub-array of the original items.

I know that this probably isn't the best verbal representation of what I'm trying to solve, so please see the following example as reference:

The original array consists of a set of objects with type x.

Original State

const data = [
  { type: "image" },
  { type: "image" },
  { type: "text" },
  { type: "image" },
  { type: "video" },
  { type: "text" },
  { type: "video" },
  { type: "video" },
];

Using JavaScript, how can I group adjacent items of type image and video into an array (following their original order), which can be accessed through the media property in an object of type module?

Desired Output

const data = [
  { type: "module", media: [{ type: "image" }, { type: "image" }] },
  { type: "text" },
  { type: "module", media: [{ type: "image" }, { type: "video" }] },
  { type: "text" },
  { type: "module", media: [{ type: "video" }, { type: "video" }] },
];

Please let me know if this makes sense and whether you have any pointers, any help would be greatly appreciated.

Thank you in advance!


Solution

    1. Initialize an empty newData array and a currentModule variable to keep track of the current module being processed.
    2. Iterate over each item in the data array. If the item's type is "image" or "video", create a new module object and add it to newData. Push the item to the media array of the current module. If the item's type is "text", add it to newData and reset the current module.
    3. Print the newData array, which contains the desired output structure with modules and media items grouped accordingly.

    const data = [
      { type: "image" },
      { type: "image" },
      { type: "text" },
      { type: "image" },
      { type: "video" },
      { type: "text" },
      { type: "video" },
      { type: "video" },
    ];
    
    let newData = [];
    let currentModule = null;
    
    for (const item of data) {
      if (item.type === "image" || item.type === "video") {
        if (!currentModule || currentModule.type !== "module") {
          currentModule = { type: "module", media: [] };
          newData.push(currentModule);
        }
        currentModule.media.push(item);
      } else if (item.type === "text") {
        if (currentModule && currentModule.type === "module") {
          currentModule = null;
        }
        newData.push(item);
      }
    }
    
    console.log(newData);