skip to Main Content

I’m having a requirement of js regex should return the object from String.

String: 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'

Output:

{
A: '100 - 200',
B: 'Test & Test2, Tes3',
C: '40',
D: '11 22',
E: 'E 444,55E'
}

I tried with following regex.

const regexp = /([^:]+): ?([^,]*),? ?/g;

But the output was not correct. Value for E is wrong.

{A: '100 - 200', B: 'Test & Test2', Tes3C: '40', D: '11 22', E: 'E 444'} 

4

Answers


  1. You could split the string and get parts for the object.

    const
        string = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E',
        parts = string.split(/, (?=[^,]:)/),
        result = Object.fromEntries(parts.map(s => s.match(/([^:]+): (.*)/).slice(1)));
    
    console.log(result);
    Login or Signup to reply.
  2. You could use some lookahead:

    const input = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'
    
    const out = {};
    for(const m of input.matchAll(/(?:^|,)s*(S+):s*([^:]+)(?=,s*S+:|$)/g)){
      out[m[1]] = m[2];
    }
    
    console.log(out);
    ` Chrome/129
    -------------------------------------------------
    Alexander  ■ 1.00x | x1000000 404 407 419 423 444
    ggg          1.35x | x1000000 546 547 552 554 565
    ------------------------------------------------- `
    

    Open in the playground

    const input = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'
    
    
    // @benchmark Alexander
    const out = {};
    for(const m of input.matchAll(/(?:^|,)s*(S+):s*([^:]+)(?=,s*S+:|$)/g)){
      out[m[1]] = m[2];
    }
    out;
    
    // @benchmark ggg
    const
        parts = input.split(/, (?=[^,]:)/);
        Object.fromEntries(parts.map(s => s.match(/([^:]+): (.*)/).slice(1)));
        
    /*@skip*/ fetch('https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js').then(r => r.text().then(eval));
    Login or Signup to reply.
  3. Similar to other answers, in one functional expression:

    const input = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'
    
    const result = Object.fromEntries(Array.from(
        input.matchAll(/([^s,:]+)s*:s*([^:]+)(?=,|$)/g), ([, ...pair]) => pair
    ));
    
    console.log(result);

    If speed is important, then use the traditional exec method:

    const input = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E'
    
    let re = /([^s,:]+)s*:s*([^:]+)(?=,|$)/g, match, result = {};
    while (match = re.exec(input)) result[match[1]] = match[2];
    
    console.log(result);
    Login or Signup to reply.
  4. The regex that you tried ([^:]+): ?([^,]*),? ? also has a match Tes3, C: 40 which is not correct besides the match for E.

    You get those matches because this part [^,]* does not match a comma, so it will stop when it encounters the first one.

    Also note that when using a pattern like this with negated character classes ([^:]+): ?([^,]*) it can also match just :

    Another version with 2 capture groups:

    b([A-Z]+):s+([^s,][^,]*(?:,(?!s+[A-Z]+:)[^,]*)*)
    

    The regex in parts match:

    • b A word boundary to prevent a partial word match
    • ([A-Z]+) Capture group 1, match 1+ chars A-Z
    • :s+ Match a colon and 1+ whitespace chars
    • ( Capture group 2
      • [^s,][^,]* Match at least 1 non whitespace char other than a comma followed by 0+ chars other than a comma
      • (?: Non capture group to repeat as a whole
        • ,(?!s+[A-Z]+:) Match a comma when not directly followed by whitespace chars, 1+ chars A-Z and a colon
      • [^,]* Match optional characters other than a comma
      • )* Close the non capture group and optionally repeat it
    • ) Close group 2

    See a regex demo

    const regex = /b([A-Z]+):s+([^s,][^,]*(?:,(?!s+[A-Z]+:)[^,]*)*)/g;
    const s = 'A: 100 - 200, B: Test & Test2, Tes3, C: 40, D: 11 22, E: E 444,55E';
    const result = Object.fromEntries(
      Array.from(
        s.matchAll(regex),
        m => [m[1], m[2]]
      )
    );
    console.log(result);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search