Home > Back-end >  string to dictionary in javascript
string to dictionary in javascript

Time:10-02

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:

enter image description here

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

Regex demo

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

Regex demo

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)
}

  • Related