I’m trying to split this string
var raw = "GMYTEOR[RHE5DO,SG[A5D[CN[I,Q],EM[I,Q],M],E5D[C[NY,OA],O,Q],M5DC[MY,NA],U5DQ,Y5DCOA]]"
I manually split this out into the following patterns:
const valid_reults = [
'GMYTEORRHE5DO',
'GMYTEORSGA5DCNI',
'GMYTEORSGA5DCNQ',
'GMYTEORSGA5DEMI',
'GMYTEORSGA5DEMQ',
'GMYTEORSGA5DM',
'GMYTEORSGE5DCNY',
'GMYTEORSGE5DCOA',
'GMYTEORSGE5DO',
'GMYTEORSGE5DQ',
'GMYTEORSGM5DCMY',
'GMYTEORSGM5DCNA',
'GMYTEORSGU5DQ',
'GMYTEORSGY5DCOA',
]
I tried parsing it with JSON.parse but that didnt work for obvious reasons.
I also tried splitting the string by the brackets but that was a really bad idea and I couldn’t get it working after 20-30 mins of trying.
What’s the best way to convert that bizarre string format into a formatted array as shown in valid_results?
Advertisement
Answer
This should work:
function splitString(str) {
// if there is no brackets a split will solve
if (!str.includes('[')) {
return str.split(',');
}
// finds first bracket
const bracketsIdx = str.indexOf('[');
// find the close bracket for it
const closingBracketsIdx =
findClosingBracketMatchIndex(str, bracketsIdx);
if (closingBracketsIdx === -1) {
// Invalid input, didn't find a close bracket
throw Error()
}
// find all possibilities inside the bracket
const expand = splitString(str.substring(
bracketsIdx+1,
closingBracketsIdx,
));
return [
// Remove duplicates
...new Set(expand.map(
(expandedStr) => splitString(
(
// concatenate each possibility to what is
// outside of the bracket
str.substring(
0,
bracketsIdx,
)
+ expandedStr
+ str.substring(
closingBracketsIdx+1,
)
)
)
// since each call will return an array we flatten them
).flat())
];
}
function findClosingBracketMatchIndex(str, pos) {
let openBracketCount = 1;
for (let i = pos + 1; i < str.length; i++) {
let char = str[i];
if (char === '[') {
openBracketCount++;
} else if (char === ']') {
openBracketCount--;
}
if (openBracketCount === 0){
return i;
}
}
return -1;
}