0

I haven't done a lot of work with regex, and I'm getting stuck. I'm trying to take a string and make it title case, but with some exceptions. I also want to remove any whitespace.

Currently it's removing whitespace and the title case is working, but it's not following the exceptions. Is there a way to combine the "title" variable with "regex" variable, and make it so the exceptions are working?

const toTitleCase = str => {
  const title = str.replace(/\s\s+/g, ' ');
  const regex = /(^|\b(?!(AC | HVAC)\b))\w+/g;
  const updatedTitle = title
    .toLowerCase()
    .replace(regex, (s) => s[0].toUpperCase() + s.slice(1));

  return updatedTitle;
}

console.log(toTitleCase(`this is an HVAC AC converter`))
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Riley
  • 21
  • 4
  • I made you a [mcve] - it seems to work – mplungjan Jan 31 '22 at 18:21
  • And what's the problem here? -> [How do I ask a good question?](http://stackoverflow.com/help/how-to-ask) – Andreas Jan 31 '22 at 18:22
  • It looks like the OP wants to exclude the words `'AC'` and `'HVAC'` from the title-case replacement. A pattern which would achieve this is e.g. [`\b(?!HVAC|AC)(?[\w])(?[\w]+)\b`](https://regex101.com/r/wshnpu/1) – Peter Seliger Jan 31 '22 at 18:39

2 Answers2

1

From the above comment ...

"It looks like the OP wants to exclude the words 'AC' and 'HVAC' from the title-case replacement. A pattern which would achieve this is e.g. \b(?!HVAC|AC)(?<upper>[\w])(?<lower>[\w]+)\b"

The code which covers all of the OP's requirements then might look like the following example ...

function toTitleCase(value) {
  return String(value)
    .trim()
    .replace(/\s+/g, ' ')
    .replace(
      /\b(?!HVAC|AC)(?<upper>[\w])(?<lower>[\w]+)\b/g,
      (match, upper, lower) => `${ upper.toUpperCase() }${ lower.toLowerCase() }`,
    );
}

console.log(
  "toTitleCase('  This  is an HVAC   AC converter. ') ...",
  `'${ toTitleCase('  This  is an HVAC   AC converter. ') }'`
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

One could take the above approach a step further by providing the to be excluded words as additional parameter(s) ...

function toTitleCase(value, ...exludedWordList) {
  const exceptions = exludedWordList
    .flat(Infinity)
    .map(item => String(item).trim())
    .join('|');
  return String(value)
    .trim()
    .replace(/\s+/g, ' ')
    .replace(
      RegExp(`\\b(?!${ exceptions })(?<upper>[\\w])(?<lower>[\\w]+)\\b`, 'g'),
      (match, upper, lower) => `${ upper.toUpperCase() }${ lower.toLowerCase() }`,
    );
}

console.log(
  "toTitleCase('  this  is an HVAC   AC converter. ', ['AC', 'HVAC']) ...",
  `'${ toTitleCase('  this  is an HVAC   AC converter. ', ['AC', 'HVAC']) }'`
);
console.log(
  "toTitleCase('  this  is an HVAC   AC converter. ', 'is', 'an', 'converter') ...",
  `'${ toTitleCase('  this  is an HVAC   AC converter. ', 'is', 'an', 'converter') }'`
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
0

const titleCaseExcluded = [
'a',
'an',
'and',
'but',
'for',
'is',
'nor',
'of',
'or',
'the',
'to'
];

function toTitleCase(textString) {
return textString.split(' ').map( word => {
    if ( titleCaseExcluded.find( exclude => exclude === word ) ) {
        return word;
    }
    return word.charAt(0).toUpperCase() + word.slice(1);
}).join(' ');
}

console.log(toTitleCase('this is an HVAC AC converter'));
9ete
  • 3,692
  • 1
  • 34
  • 32