tengo una cadena, necesito convertirla en una matriz de objetos
const str = "addias (brand|type) sneakers(product) for men(o)"Rendimiento esperado
let output = [ { key:"addias", value:["brand","type"] }, { key:"sneakers", value:["product"] }, { key:"for men", value:[] } ]código que probé
function gerateSchema(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 = gerateSchema(str) pero esta rompiendo cuando hay alguna palabra con espacio por ejemplo for men
cómo dividir con una expresión regular
Un enfoque sería primero hacer una expresión regular para encontrar todas las combinaciones de clave/valor en la cadena original. Luego, repita ese resultado y cree un mapa hash usando las claves de palabras y los valores de matriz.
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);La primera expresión regular coincide con cada cadena de clave/valor:
\w+ match a word (?: \w+)* followed by a space, and another word, the quantity zero or more times \s* optional whitespace \( ( .*? pipe separated value string \) ) Luego, dividimos cada término en \s*(?=\() , que son los espacios que preceden inmediatamente al término (...|...) . Finalmente, dividimos la cadena de valor en la tubería | para generar el conjunto de valores.
Una forma alternativa podría ser esta.
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)Con un poco de ayuda de regex101.com , derivó las siguientes expresiones regulares y el siguiente código.
([^\(]+)\(([^\)]*)\) que se descompone en
([^\(]+) - captura 1 o más caracteres hasta el primero ( como grupo 1
\( - tragarse los paréntesis izquierdos
([^\)]*) - captura todo hasta la próxima aparición de ) como grupo 2
\) - tragar los padres correctos
y estaba empezando a [^|]+ - para analizar el texto del grupo 2, pero en realidad es más simple con una declaración de split simple.
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));