Transform the array into several different arrays

Having some trouble manipulating this array to get it into the desired form.

This is the initial array:

const children = [
  { type: 'span' },
  { type: 'br' },
  { type: 'span' },
  { type: 'br' },
  { type: 'br' },
  { type: 'span' },
  { type: 'br' },
  { type: 'br' },
  { type: 'br' },
  { type: 'span' },
  { type: 'br' },
  { type: 'span' },
]

The goal is to create an array of arrays where consecutive br values indicate a new subarray. The desired outcome should look like this:

[
  [{type: 'span'}, {type: 'br'}, {type: 'span'}],
  [{type: 'span'}],
  [{type: 'span'}, {type: 'br'}, {type: 'span'}]
]

Please Note: There can be any number of consecutive br tags in the original array.

Considering whether using reduce would be a more efficient approach compared to forEach.

Answer №1

To optimize the array, consider reducing it.

const
    items = [{ item: 'apple' }, { item: 'orange' }, { item: 'banana' }],
    separator = 'comma',
    outcome = items.reduce((result, object, index, arr) => {
        if (object.item === separator) {
            if (arr[index - 1]?.item === separator) {
                if (result[result.length - 1].length) result.push([]);
                return result;
            } else if (arr[index + 1]?.item === separator) return result;
        }
        result[result.length - 1].push(object.item);
        return result;
    }, [[]]);
    
console.log(outcome);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №2

It may seem like a simple solution, but it could be worth considering using a different separator instead of \n for better data organization.

let elements = [
  'h1',
  'br',
  'h2',
  'br',
  'br',
  'p',
  'br',
  'br',
  'br',
  'br',
  'br',
  'br',
  'br',
  'br',
  'br',
  'p',
  'br',
  'h3'
]

console.log(elements.join("\n").split(/(?:\nbr){2,}\n/).map(element => element.split("\n")))

This method definitely does the job...

Answer №3

const formattedString = children
  .map(({ type }) => type) // converting to array of strings
  .map(type => (type === 'br' ? ' ' : type)) // replacing 'br' with space for further processing
  .join('') // converting to a long string 
  .split('  ') // splitting by two 'br's
  .map(row => row.trim()) // removing leading and trailing 'br's
  .map(row => (
    row.replace(' ', '|br|') // restoring 'br'
      .split('|') // splitting into an array
      .map(value => ({ type: value })) // restoring original structure
   )
  );

console.log(formattedString);

Answer №4

There's a method using reduce that I've put together, but I'm not entirely convinced of its efficiency. Take a look:

const children = [{"type":"span"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"br"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"span"}];

const is_br = (item) => item?.type === 'br';

const result = children.reduce(
  (acc, val, i, { [i - 1]: prev, [i + 1]: next }) => {
    if(!is_br(prev) && is_br(val) && is_br(next))
      acc.push([]);
  
    if(is_br(val) && (is_br(prev) || is_br(next)))
      return acc;
    
    acc[acc.length - 1].push(val);
    
    return acc;
  },
  [[]]
);

console.log(result);

Here's a revised version that could potentially function similarly to your original code snippet:

const children = [{"type":"span"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"br"},{"type":"br"},{"type":"span"},{"type":"br"},{"type":"span"}];

let paragraphs = []
let elements = []
let flag = false
children.forEach((child, idx) => {
  if (child.type !== 'br') {
    flag = false
    elements.push(child)
  } else {
    if (flag) {
      if(elements.length > 1) {
        paragraphs.push(elements.splice(0, elements.length - 1))
      }
      elements = []
    } else {
      elements.push(child)
      flag = true
    }
  }
  
  if(idx === children.length - 1 && elements.length > 0)
    paragraphs.push(elements)
});

console.log(paragraphs);

Answer №5

Below is a versatile solution that performs the following tasks: 1) transforms an array of objects into a string, 2) divides the string based on multiple instances of b, and 3) reverts the split string back into objects:

const children = [
  { type: "span" },
  { type: "br" },
  { type: "span" },
  { type: "br" },
  { type: "br" },
  { type: "span" },
  { type: "br" },
  { type: "br" },
  { type: "br" },
  { type: "span" },
  { type: "br" },
  { type: "span" },
];

const map = { s: "span", b: "br" };

console.log(
  children
    .reduce((s, o) => (s += o.type[0]), "")   // converting object array to a string
    .split(/b{2,}/)                           // splitting string when encountering 2 or more 'b's
    .map((s) => {                             // reverting split strings back into object arrays
      const res = [];
      for (const ch of s) {
        res.push({ type: map[ch] });
      }
      return res;
    })
);

Answer №6

Using While Loops for Solution.

  • We utilize two variables in this solution - i as a counter and temp to store different array slices.

  • The next step involves a nested while loop, where the first one is for looping and the second is to skip all consecutive occurrences of "br".

  • A flag is employed to verify if the second while loop was executed.

    • If it ran, we push the contents of temp into the resultant array res and clear temp.

    • If not, we continue pushing elements to temp.

Furthermore, there are certain checks implemented to handle specific edge cases.

const children = [{type:"span"},{type:"br"},{type:"span"},{type:"br"},{type:"br"},{type:"span"},{type:"br"},{type:"br"},{type:"br"},{type:"span"},{type:"br"},{type:"span"}];

const res = [];

let i = 0;
let temp = [];

while (i < children.length) {
  let flag = false;
  while (i < children.length && children[i].type === "br" && children[i + 1]?.type === "br") {
    i++;
    flag = true;
  }
  if (flag) { res.push(temp); temp = []; i++; }
  if (i >= children.length) break;
  temp.push(children[i]);
  i++;
}

if (temp.length > 0) res.push(temp);

console.log(JSON.stringify(res));

Utilizing RegEx for the Solution Approach

(Adapted from Ralkov's approach)

const 
 children = [{type:"span"},{type:"br"},{type:"span"},{type:"br"},{type:"br"},{type:"span"},{type:"br"},{type:"br"},{type:"br"},{type:"span"},{type:"br"},{type:"span"}],

 res = children
  .map(({ type }) => `${type} `)
  .join("")
  .replace(/(?:br\s){2,}/g, " ")
  .trim()
  .split("  ")
  .map((s) => s.split(",").map((type) => ({ type })));
  
console.log(JSON.stringify(res));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the method for applying a Redux statement?

Experience with Redux toolkits: https://i.sstatic.net/cwu8U.png I've encountered an issue while working with Redux toolkits where I'm unable to access certain statements. I attempted the following code snippet, but it resulted in an error. c ...

Implementing dynamic title rendering based on image in vue.js

This is the code I'm working with, aiming to display slider data. My goal is that if image[0] appears on the slider, it should return title [0]. I'm quite curious about what could be missing in my setup.code-image ...

What could be causing my onclick code to activate on double click the very first time?

Currently, I am developing a straightforward popup for my Nextjs website. The implementation involves using the onclick attribute to toggle the display property in CSS between none and block based on the ID of the element. Although the functionality works ...

The error states that the type '() => string | JSX.Element' cannot be assigned to the type 'FC<{}>'

Can someone help me with this error I'm encountering? I am fairly new to typescript, so I assume it has something to do with that. Below is the code snippet in question: Any guidance would be greatly appreciated. const Pizzas: React.FC = () => { ...

Apologies, we are experiencing a server error. TypeError: Unable to access the 'map' property of an undefined

I'm struggling to grasp the concept of fetching external data using server-side rendering with the getServerSideProps method. In particular, I am facing difficulties with the search functionality and how to handle the returned data. As someone who is ...

Promise.all doesn't pause for Firestore queries to iterate

The code I am converting from the Realtime Database to Firestore involves looping through each User (doc) in Firestore and then through each document of 2 nested Subcollections inside each User in order to create some jobs to be handled later. Although I ...

Running Javascript code to perform drag and drop in Selenium for UI integration testing in Java

I am currently working on a task involving writing UI test cases (Automation) using Selenium in Java. I have an HTML page with an element that needs to be dragged to a target. Despite trying the Action functionality in Selenium, it didn't work for me. ...

Not receiving connections on localhost port 3000

Our team has successfully created a basic Express Node website https://i.stack.imgur.com/5fwmC.png We attempted to run the app using DEBUG=express_example:* npm start https://i.stack.imgur.com/NI5lR.png We also tried running it with node DEBUG=express_ ...

Is object equality compromised when using track by with ngOptions in AngularJS 1.4 migration?

Seeking assistance to clarify an issue that arose after transitioning from Angular 1.3 to Angular 1.4. I have prepared a JSFiddle demo to showcase this problem. Explanation In my controller, there are two instances of MyElement in a list that a user can ...

Questions on how to utilize ES6 Express and static methods

Recently, I've been working with Express and wanted to incorporate ES6 using babel in my project. One question that has been on my mind is related to the use of static methods for handling requests, as shown below: class MyCtrl { static index (r ...

Activate a function upon the clicking of a button by utilizing a directive in Angular.js

In my directive, there is a function called "myFunction()", and in the template, I have a button. When the button is clicked, I want to execute the function without using ng-click for specific reasons. Instead, I am looking to assign a class to the button ...

"Exploring the Intersection of Meteor, NPM Packages, and Fiber Callbacks

I am currently utilizing request and cheerio to extract specific content, particularly a quote, from a website. Here is the code snippet ( server.js ) : q = new Mongo.Collection('quotelist'); postList = new Mongo.Collection('quotes&apos ...

A guide to eliminating TextRow and inserting a string into JSON using NodeJs

To remove TextRow and add the string true to JSON in NodeJs, I have included the following code: NodeJs Code: function groupBy(objectArray, property) { return objectArray.reduce(function (acc, obj) { let key = obj[property] if (!acc[key]) { ...

ajaxform is not providing the correct response

There is a form below that logs into Instagram based on the response it receives. If the login is successful (returns "ok"), then it shows success, otherwise it should display an error state. However, in my case, it always returns a null state for some un ...

the input text box does not respond to click events

This is the input I have: <input name="DeviceIP" class="k-input k-textbox" type="text" data-bind="value:DeviceIP"> Below is my JavaScript code that seems to not be functioning properly: $('input[name="DeviceIP"]').click(function () { al ...

When trying to access the "form" property of a form ElementRef, TypeScript throws an error

I've encountered an issue with accessing the validity of a form in my template: <form #heroForm="ngForm" (ngSubmit)="onSubmit()"> After adding it as a ViewChild in the controller: @ViewChild('heroForm') heroForm: ElementRef; Trying ...

Is there a way for me to detect click events on Windows notifications?

Currently, I am attempting to send notifications through the node-notifier package. The goal is for a click on the notification to lead to a specific link. However, I am encountering difficulties in listening to the click event - the events provided by the ...

Using the Printf Function to Print Elements of a 2D Array

When attempting to print elements from an array, I noticed that each line is only displaying 3 characters instead of the full 4 characters that define each element. Is there a specific setting in Printf that needs to be adjusted for this? printf("at tim ...

Angular $http.get: How to handle errors effectively?

When sending a form to Node.js for authentication, I am using $http.get in the following function and adding a promise with .then. Will this handle all possible errors that may occur from the server in production? Is there anything else I need to include i ...

determining collisions between the character in my game and a specific block within a 2-dimensional array

Currently, I am working on a fun game project that involves some collision issues. The setup includes a player character drawn on one canvas and blocks (16x16px) drawn on another canvas. However, I am facing difficulties in detecting horizontal collision ...