Necesito escuchar una entrada y obtener su valor dinámicamente, cuando se escribe una "bandera" específica, obtener lo que se escriba a continuación hasta que aparezca una bandera nuevamente.
Dejame explicar :
digamos que tengo una serie de "banderas"
let flags = ['foo','bar','baz']
y tengo una entrada para escuchar que me da la siguiente cadena (dinámicamente, carácter por carácter):
let input = "whateveridontneedthatfoodavidbarjennifer-andrew-billbazericfoojohnbarchristen"
* foo
y bar
aparecen dos veces y baz
una vez
quiero de alguna manera crear, tal vez un objeto como este:
{ foo: ["david","john"], bar: ["jennifer-andrew-bill","christen"], baz: ["eric"] }
o 3 matrices separadas, realmente no me importa la estructura siempre que filtre el valor correctamente
Buena respuesta de @Apple BS, solo quiero proponer esta sintaxis:
const flags = ['foo', 'bar', 'baz'] const str = 'whateveridontneedthatfoodavidbarjennifer-andrew-billbazericfoojohnbarchristen' const strSplit = str.split(new RegExp(`(${flags.join('|')})`, 'g')) const obj = Object.fromEntries(flags.map(f => [f, []])) strSplit.forEach((el, i) => { if (flags.includes(el)) obj[el].push(strSplit[i + 1]) }) console.log(obj)
EDITAR:
Hay otra versión que usa grupos de captura de expresiones regulares.
const str = 'whateveridontneedthatfoodavidbarjennifer-andrew-billbazericfoojohnbarchristen' const flags = ['foo', 'bar', 'baz'], flagsJoin = flags.join('|') const obj = Object.fromEntries(flags.map(f => [f, []])) const regex = new RegExp(`(${flagsJoin})(.*?)(?=${flagsJoin}|$)`, 'g') for (const [, flag, sub] of str.matchAll(regex)) obj[flag].push(sub) console.log(obj)
Primero, construye una expresión regular:
let regex = '('; // parenthesis is added for capturing groups, which means the flags will be captured too for (f of flags) regex += f + '|'; regex = new RegExp(regex.substring(0, regex.length - 1) + ')', 'g'); // construct the regex with global flag // regex = /(foo|bar|baz)/g
Luego, divide la cadena:
s = s.split(regex) // ["whateveridontneedthat", "foo", "david", "bar", "jennifer-andrew-bill", "baz", "eric", "foo", "john", "bar", "christen"]
Finalmente, recorra la cadena dividida y agréguela al objeto.
A continuación se muestra el ejemplo completo:
let flags = ['foo', 'bar', 'baz']; let s = "whateveridontneedthatfoodavidbarjennifer-andrew-billbazericfoojohnbarchristen"; let regex = '('; let obj = {}; for (f of flags) regex += f + '|'; regex = new RegExp(regex.substring(0, regex.length - 1) + ')', 'g'); s = s.split(regex); for (let i = 0; i < s.length; i++) { for (let j = 0; j < flags.length; j++) { // checking for flags if (s[i] == flags[j]) { // found the flag if (flags[j] in obj) obj[flags[j]].push(s[i + 1]); // array exist in object else obj[flags[j]] = [s[i + 1]]; // create array in object i++; // skip next s[i] break; // s[i] can only be one of the flag } } } console.log(obj);
Además de la respuesta de @AppleBS y @Jean Will,
Simplemente simplifique el bucle for.
const flags = ["foo", "bar", "baz"]; const str = "whateveridontneedthatfoodavidbarjennifer-andrew-billbazericfoojohnbarchristen"; const strSplit = str.split(new RegExp(`(${flags.join("|")})`, "g")); const output = strSplit.reduce((carry, item, idx, arr) => { if (idx !== 0) { if (idx % 2 === 0) carry[arr[idx - 1]].push(item); else if (!carry[item]) carry[item] = []; } return carry; }, {}); console.log(output);