Ryan
Ryan

Reputation: 25

string to dictionary in javascript

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!

Upvotes: 1

Views: 1104

Answers (4)

The fourth bird
The fourth bird

Reputation: 163287

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

Upvotes: 0

Jair Lopez Gutierrez
Jair Lopez Gutierrez

Reputation: 174

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

Upvotes: 0

Andy
Andy

Reputation: 63524

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

Upvotes: 1

Wu Wei
Wu Wei

Reputation: 2277

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.

Upvotes: 1

Related Questions