xShirase
xShirase

Reputation: 12399

Capitalize First letter, lowercase the rest, with exceptions

I have some data I need to format by capitalizing the first letter of each word, and lowercasing the rest. I am using the following :

function toTitleCase(str){
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

It works but I need to add exceptions to it, all values being in an array : [USA,U.S.A,7UP,PC,SlimFast,...]

These values are sometimes upper, sometimes lower, sometimes mixed and need to not be modified. Any ideas?

Upvotes: 2

Views: 8385

Answers (5)

xShirase
xShirase

Reputation: 12399

Solved using the following function.

function toTitleCase(str){
      return str.replace(/\w\S*/g, function(txt){
        if(['PC','USA','U.S.A'].includes(txt))===-1){
          return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        } else {
          return txt;
        }
      });
    }

name = toTitleCase(name);

Upvotes: 2

thgaskell
thgaskell

Reputation: 13226

It might not be exactly what you need, but the general idea:

  1. Split/target each word.
  2. Check if it doesn't match a word in the ignore list (using the i flag to ignore capitalization)
  3. If it doesn't, capitalize it,
  4. If it does, leave it alone.
var s = "UsA bar U.S.A. fOO slimfast bAz",
    ignore = ["USA", "U.S.A", "7UP", "PC", "SlimFast"],
    regex = new RegExp(ignore.join("|"), 'i'),

    result = s.split(' ').map(function(word){
        return (regex.test(word)) ? word : capitalize(word);
    }).join(' ');

// "UsA Bar U.S.A. Foo slimfast Baz"

function capitalize(s) {
    return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
}

Upvotes: 1

Adassko
Adassko

Reputation: 5343

function toTitleCase(str){
    var cantTouchThis = {'USA' : 1, 'U.S.A' : 1, '7UP' : 1, 'PC' : 1, 'SLIMFAST' : 1};
    return str.replace(/\w[\S.]*/g, function(txt){return cantTouchThis[txt.toUpperCase()] ? txt : txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

the keys is an uppercase of string which you don't want to replace

the values can be anything that evaluates to true


but you may also want to give the only correct casing in value - something like:

function toTitleCase(str){
    var cantTouchThis = {'USA' : 'USA', 'U.S.A' : 'USA', '7UP' : '7Up', 'PC' : 'PC', 'SLIMFAST' : 'SlimFast'};
    return str.replace(/\w[\S.]*/g, function(txt){return cantTouchThis[txt.toUpperCase()] || txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

this way string like:

UsA U.S.A anything slimfast

will become:

USA USA Anything SlimFast

Upvotes: 1

Tibos
Tibos

Reputation: 27823

EDIT: It seems i didn't quite understand that the exceptions are entire words. The answer below deals with exceptions being part of the words.

I'm not particularly sure this is the best solution, but you could get an array of matches to your exceptions, then run your function, then replace the matches back.

var exceptions = ['USA','U\.S\.A','7UP','PC','SlimFast']; //escaped strings!

var matcher = new RegExp(exceptions.join('|'), 'gi');

var str = 'tuSalolpCOKyes'; //test string

var matches = str.match(matcher); // extract replacements


var str = toTitleCase(str); // run your function

// replace stuff you didn't want changed
var index = 0;
var str = str.replace(matcher, function() {
  return matches[index++];
});

console.log(str); // RESULT: TuSalolpCokyes


// your function
function toTitleCase(str){
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

Upvotes: 0

spectralbat
spectralbat

Reputation: 407

What about something along the lines of this:

function toTitleCase(str){
    var ignore = inArray(exceptionsArr, str);
    if (!ignore) {
        return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
    }
    return str;
}


inArray: function(arr, obj) {
    return (arr.indexOf(obj) != -1);
},

Alternatively if your str is an entire sentence with the exception words inside it, you can split the str into individual words and then run each word through the above process with a for loop.

Upvotes: 2

Related Questions