What is the best way to use regex for splitting an array?

I have a string that I need to convert into an array of objects

const str = "Nike (brand|category) shoes(product) for women(o)"

Expected result

let output = [
 { 
  key:"Nike",
  value:["brand","category"]
 },
{ 
  key:"shoes",
  value:["product"]
 },
{ 
  key:"for women",
  value:[]
 }

]

Here is the code I attempted

function generateSchema(val) {
       let split = val.split(" ")
       let maps = split.map((i) => {
           let obj = i.split("(")
           let key = obj[0].replaceAll(/\s/g, "")
           let cleanValue = obj[1].replace(/[{()}]/g, "")
           let stripedValues = cleanValue.split("|")

           return {
               key: key,
               value: stripedValues,
           }
       })
       return maps

}
let out = generateSchema(str)

However, this breaks when there is a word with a space, for example for women

How can I split with a regex?

Answer №1

To efficiently extract key/value pairs from a string, one method involves using regex to identify all instances of these combinations. By iterating through the results, a hashmap can be constructed with the keys as words and the values as arrays.

var str = "addias (brand|type) sneakers(product) for men(o)";
var matches = str.match(/\w+(?: \w+)*\s*\(.*?\)/g, str);
var array = [];
for (var i=0; i < matches.length; ++i) {
    var parts = matches[i].split(/\s*(?=\()/);
    var map = {};
    map["key"] = parts[0];
    map["value"] = parts[1].replace(/^\(|\)$/g, "").split(/\|/);
    array.push(map);
}
console.log(array);

The initial regex pattern targets each key/value pair in the string:

\w+        captures a word
(?: \w+)*  followed by additional words and spaces multiple times
\s*        optional spaces
\(         (
.*?        non-greedy match for content within parentheses
\)         )

Subsequently, splitting occurs on \s*(?=\(), identifying spaces preceding a (...|...) segment. The values are then separated using the pipe symbol |.

Answer №2

Here is an alternative approach.

const str = "addias (brand|type) sneakers(product) for men(o)"
const array = str.split(')').filter(i => i.length).map(i => {
   const item = i.split('(');
   return {
     key: item[0].trim(),
     value: item[1].split('|')
   }
})

console.log(array)

Answer №3

To simplify the process, consider utilizing the exec method to loop through the patterns identified by the regex.

const str = 'addias(brand|type|size|color) sneakers(pro) for men(o)';

// This regex locates a group of letters initially,
// then matches the text inside the parentheses
const regex = /([a-z]+)\(([a-z\|]+)\)/g;

let myArray;
const arr = [];

while ((myArray = regex.exec(str)) !== null) {

  // Extract the key and the delimited string
  const [_,  key, ...rest] = myArray;

  // Split the string found in `rest` first element
  const values = rest[0].split('|');

  // Add a new object to the output array
  // (excluding "o" for some reason)
  arr.push({
    key,
    value: values.filter(v => v !== 'o')
  });
}

console.log(arr);

Answer №4

Utilizing the resources of regex101.com, I uncovered the following regex expressions and subsequent code.

([^\(]+)\(([^\)]*)\) can be broken down into

([^\(]+) - capturing 1 or more characters until the first ( as group 1

\( - absorbing the left parenthesis

([^\)]*) - capturing everything until the next ) as group 2

\) - absorbing the right parenthesis

Initially, I tried using [^|]+ to dissect the text of group 2, but it turned out to be more streamlined with a simple split statement.

    function generateSchema(str) {
        const regex = /([^\(]+)\(([^\)]*)\)/mg;  // captures the 'word (word)' pattern
        let m;
        let output = [];
        let obj = {};
    
        while ((m = regex.exec(str)) !== null) {
    
            // This is necessary to avoid infinite loops with zero-width matches
            if (m.index === regex.lastIndex) {
                regex.lastIndex++;
            }
        
            m.forEach((match, groupIndex) => {
                if (groupIndex === 1) {
                    obj = {};
                    obj.key = match.trim();
                } else if (groupIndex === 2) {
                    obj.value = match.split('|').map(i=>i.trim());
                    output.push(obj);
                }
            });
        }
        return output;
    }

    const str = "addidas (brand | type  ) sneakers(product) for men(o)";
    console.log(generateSchema(str));

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

Issue with height in self-invoking function not functioning correctly

Issue with height not functioning correctly inside self-invoking function, but works fine within (document).ready(function() (function($){ var clientHeight = document.getElementById('home').clientHeight; alert(clientHeight); })(jQuery); <di ...

Kendo UI Web - MultiSelect: choosing an option multiple times

Currently, I am encountering an issue with the Kendo UI MultiSelect widget when trying to select an option multiple times. An example of this is shown in the image below where I want to choose Schindler's List again after selecting The Dark Knight. Ho ...

Enhancing Navbar Design with Tailwind CSS in NextJS and React

I have not worked with React in a while and just started learning Next.Js. I am trying to figure out how to change the background of my Navbar using Tailwind CSS based on a boolean value "current" (true/false) depending on which page the user is on with Ne ...

I am attempting to retrieve the initial three results from my MySQL database using Node.js, but I keep encountering an error

Below is the code I am currently using: con.query('SELECT * FROM tables', function(err, results) { if (err) throw err console.log(results[0].rawname) for(var i= 0; i <= 3; i++) { ...

What is the best way to implement rate limiting for Next.js server actions?

In my current project, I have implemented server actions in next.js following the guidelines provided on Server Actions Although everything is functioning properly, I am now looking to add rate limiting to the server action to prevent potential spam or at ...

Guide to activating a reaction following an occurrence in a React component

I have started developing a React application that loads blog posts along with their associated comments. The challenge I am facing is how to trigger a refresh of the comments component and display the new comment immediately after it has been submitted. ...

Having trouble accessing the iframe element in an Angular controller through a directive

My webpage contains an iframe with a frequently changing ng-src attribute. I need to execute a function in my controller each time the iframe's src changes, but only after the iframe is fully loaded. Additionally, I require the iframe DOM element to b ...

A guide on how to activate an event when a radio button is selected using jQuery

I experimented with implementing this. When I try clicking on the radio button, the code functions correctly, but the radio button does not appear to be checked and remains unchanged. Any ideas on how to resolve this issue? <p> <input id="p ...

Deactivating Timeout Requests in Koa Server

I keep encountering a connection reset error. I strongly believe it's stemming from a lengthy REST request, causing it to timeout. { [Error: socket hang up] code: 'ECONNRESET' } Is there a method to deactivate request timeouts within Koa, ...

Error: Google chart for Google Maps is not displaying text every 1 unit as expected

I am looking to display all the hAxis labels in my chart. Due to the extensive length of the code exceeding 4000 lines, I will only include what I consider to be crucial: var data = new google.visualization.DataTable(); data.addColumn('string', & ...

Is it possible to attach React Components to Elements without using JSX?

In my React Component, I have the following code: import React, { useEffect } from 'react' import styles from './_PhotoCollage.module.scss' import PhotoCard from '../PhotoCard' const PhotoCollage = ({ author }) => { let ...

The pagination feature in React MUI DataGrid is malfunctioning

I am currently working with a datagrid and implementing server-side pagination. I have set a limit of 5 objects to be returned from the backend, and an offset variable to indicate from which index the next set of data should come. const handlePageChange = ...

Angular 5 with Typescript encountered a failure in webpack due to the absence of the property "data" on the Response

I am encountering an issue during webpack compilation. It compiles successfully if I remove .data, but then the page crashes with calls from template->component (which in turn calls a service). Here is the error I am facing: ERROR in src/app/compone ...

Is it possible for an ul to be displayed beneath a white section within an li

I am working on a JQuery carousel that is displaying correctly, but I want to make a small adjustment to the content: <li class="jcarousel-item jcarousel-item-horizontal jcarousel-item-1 jcarousel-item-1-horizontal" style="float: left; list-style: none ...

E6 arrow functions simplify the process of condensing an array of objects into a single object

Here is an array that I have: a=[{'test':1,'test2':'2'},{'test':3,'test2':'4'}] My goal is to reduce this array into a single object This is the expected output {1:2,3:4} I attempted the foll ...

How can I use jQuery to hide each div of the same class individually when a user clicks on each div to close

I am working on a project where I have multiple notification boxes represented by divs with the same class. These boxes are set to fade in one after the other using jQuery. Each box also contains a 'close_box' div that acts as a button to close/h ...

Choose a value to apply to the dropdown menus

I've encountered an issue with the following code - it only seems to work once and not every time: var selectedVal = $('#drpGender_0').find("option:selected").text(); if (selectedVal == "Male") { $('#drpGender_1').fi ...

Why is my JSON object showing up as undefined in my Node.js POST request?

I have a CentOS server that is currently running a node.js HTTP server (code provided below). My goal is to pass JSON data from the command line by using the following CURL command: curl -X POST -H "application/json" -d '{"val1":"hello","val2":"my"," ...

How can I use an input array to filter data in mongodb?

When receiving input from the front-end, it looks like this: { "options":[ { "optionId":"5ebbe0f56b197f36fc472168" }, { "optionId":"5ebbe1aa6b197f36fc47216e" } ] } The goal is to filter the data in a way that ...

Ways of accessing an array within an if statement

I have a dashboard with admin privileges for my application. In this dashboard, the admin can select a user from a dropdown list. Once a user is selected, I make an AJAX call to retrieve the user's data and store it in a variable named $result. Howeve ...