javascriptregexavatar

Best way to make a RegExp that returns 2 initials of a name?


I was trying to make a RegExp with the following expected results:

Input: James Cameron
Expected: JC

Input: James cameron
Expected: JC

Input: James
Expected: JA

Input: James Francis Cameron
Expected: JF

I gave up and ended using the following JS code:

function initials(name) {
    return name.toUpperCase().split(/\s+/g).map((s, _i, arr) => (arr.length > 1 ? s[0] : s[0] + s[1])).reduce((a, b) => a + b).substring(0,2);
}

Making two separated regular expressions was also easy (for example: name.replace(/^\s*([a-z]).+?\s+([a-z]).*$/, '$1$2'))

However i understand it should be a way to fulfill this using only one RegExp.


UPDATE: Later on, I had one more test-string. The accepted answer didn't worked for it: James Francis Cameron as the expected result was JF.

I solved it by using the following regex, and replace with $1$2$3:

^\s*(\S)(?:.+?\s(\S)|(\S)).*$ 

Solution

  • You may use

    .replace(/^(\S{2})\S*$|(?:^|\s*)(\S)\S*\s*/g, '$1$2').toUpperCase()
    

    See the regex demo and the JavaScript demo:

    const initials = (name, regex) => name.replace(regex, '$1$2').toUpperCase()
    
    const arr = ['Elon Musk','Elon musk','Elon'];
    const rex = /^(\S{2})\S*$|(?:^|\s*)(\S)\S*\s*/g;
    arr.forEach( x => console.log(x, "=>", initials(x, rex)) );

    Regex details