I have a string that I want to transform into a dictionary, the string looks like this:
const str = '::student{name="this is the name" age="21" faculty="some faculty"}'
I want to transform that string into a dictionary that looks like this:
const dic = {
"name": "this is the name",
"age": "21",
"faculty": "some faculty"
}
So the string is formated in this was ::name{parameters...}
and can have any parameters, not only name
, faculty
, ... How can I format any string that looks like that and transform it into a dictionary?
Also Is there a way to check that the current string I'm parsing follow this structure ::name{parameters...}
, that way I can throw an error when it does not.
Any help would be greatly appreciated!
CodePudding user response:
Assuming that you only have alphanumeric and spaces or an empty string within the parentheses of the values, and there is never a space between the key and value in key="value"
you can match with the following regular expression and then iterate over it to construct your desired object.
const str = '::student{name="this is the name" age="21" faculty="some faculty"}'
const matches = str.match(/[\w] \=\"[\w\s]*(?=")/g)
const result = {}
matches.forEach(match => {
const [key, value] = match.split('="')
result[key] = value
})
console.log(result)
The regex is composed of the following parts:
You can use https://regexr.com to experiment with your regular expressions. Depending on the string to process, you'll need to refine your regex.
CodePudding user response:
This example uses exec
to look for matches in the string using a regular expression.
const str = '::student{name="this is the name" age="21" faculty="some faculty"}';
const regex = /([a-z] )="([a-z0-9 ?] )"/g;
let match, output = {};
while (match = regex.exec(str)) {
output[match[1]] = match[2];
}
console.log(output);
CodePudding user response:
If not exist a unique pattern, it is hard, but when pattern is the same, you can split the string:
var str = '::student{name="this is the name" age="21" faculty="some faculty"}'
console.log(createObj(str));
function createObj(myString){
if(myString.search("::") !== 0 && myString.search("{}") === -1 && myString.search("}") === -1){
console.log("format error")
return null;
}
var a = myString.split("{")[1];
var c = a.replace('{','').replace('}','');
if(c.search('= ""') !== -1){
console.log("format incorrect");
return null;
}
var d = c.split('="')
var keyValue = [];
for(item of d){
var e = item.split('" ')
if(e.length === 1){
keyValue.push(e[0].replace('"',''));
}else{
for(item2 of e){
keyValue.push(item2.replace('"',''));
}
}
}
var myObj = {}
if(keyValue.length % 2 === 0){
for(var i = 0; i<keyValue.length; i=i 2){
myObj[keyValue[i]] = keyValue[i 1]
}
}
return myObj;
}
CodePudding user response:
You could use 2 patterns. The first pattern to match the format of the string and capture the content between the curly braces in a single capture group. The second pattern to get the key value pairs using 2 capture groups.
For the full match you can use
::\w {([^{}]*)}
::\w
match::
and 1 word characters{
Match the opening curly([^{}]*)
Capture group 1, match from opening till closing curly}
Match the closing curly
For the keys and values you can use
(\w )="([^"] )"
(\w )
Capture group 1, match 1 word chars="
Match literally([^"] )
Capture group 2, match from an opening till closing double quote"
Match closing double quote
const str = '::student{name="this is the name" age="21" faculty="some faculty"}';
const regexFullMatch = /::\w {([^{}]*)}/;
const regexKeyValue = /(\w )="([^"] )"/g;
const m = str.match(regexFullMatch);
if (m) {
dic = Object.fromEntries(
Array.from(m[1].matchAll(regexKeyValue), v => [v[1], v[2]])
);
console.log(dic)
}