-2

Basically, I'd like to do the following:

    McDonald => McDONALD
    McDowell => McDOWELL
    McIntosh => McINTOSH
    etc.

I'm also looking into things like iPhone => iPHONE, but I'm probably just going to use a set list for that. However, the names change regularly, and it would be an inconvenience to keep a running list.

Is it possible to do this? I was looking at regex, but I couldn't think of a way to do it without lookbehind (I'm using JavaScript).

jhpratt
  • 6,841
  • 16
  • 40
  • 50
  • 1
    By the look of it you don't have a clear defined pattern for every case (McDonald [2 first letter], iPhone [1 letter]), so I would go for a list of prefixes, then substring that prefix from the word then make everything else uppercase join then two! – Jorge Campos Jul 17 '15 at 02:23
  • @Xufox I'm working in Javascript, which doesn't have lookbehind – jhpratt Jul 17 '15 at 02:24
  • In javascrit you can't do this kind of replacing with regex. – Jorge Campos Jul 17 '15 at 02:25
  • 1
    This seems like an incredibly strange thing to do. If you're not going to uppercase the `c` in `Mc`, why do you uppercase everything after it? – Barmar Jul 17 '15 at 02:28
  • It's for scripting (a teleprompter), where everything is in all caps (for readability reasons). Although it isn't bad to have a name in all caps (when one should be lowercase), there are frequent occasions on which this would be useful (since the town it's for has two capitals) – jhpratt Jul 17 '15 at 02:30

1 Answers1

6

This seems to work:

var convertName = function(name){
  var pattern=/^(.*?[a-z][A-Z])(.*)$/g;
  if(pattern.test(name)){
    return name.replace(pattern,function(t,a,b){
      return a+b.toUpperCase();
    });
  }
  else{
    return name.toUpperCase();
  }
};

It basically looks for the first upper-case letter after the first lower-case letter, separates that first part from the rest and makes the rest upper-case. This only happens, if such a pattern is found. Otherwise it simply returns the name in upper-case.

Usage

convertName('McDonald'); // McDONALD
convertName('McDowell'); // McDOWELL
convertName('McIntosh'); // McINTOSH
convertName('iPhone'); // iPHONE
convertName('Smith'); // SMITH

Replacing multiple instances

The simplest way is by matching every group of letters and putting that into the function. You can use:

"Word, test, “words”, McIntosh is a name, just like Herbert-McIntosh. So much upper-case.".replace(/(\w+)/g,function(t,w){
  return convertName(w);
});
// "WORD, TEST, “WORDS”, McINTOSH IS A NAME, JUST LIKE HERBERT-McINTOSH. SO MUCH UPPER-CASE."
//                                        Prefix after a dash ^^^
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
  • If there's no `McX` at the beginning, I think he wants to uppercase the whole thing. So `Smith` should become `SMITH`. – Barmar Jul 17 '15 at 02:33
  • @Barmar then why he wants this `iPhone => iPHONE` ? – Avinash Raj Jul 17 '15 at 02:37
  • he said that's a special case – Barmar Jul 17 '15 at 02:44
  • This is for a TelePrompTer, so normal text is uppercase. He's only using mixed case for prefixes like `i` and `Mc`. – Barmar Jul 17 '15 at 02:45
  • This answer is definitely the best! I'm just searching for a way to implement this to loop through every word to check it (unless there's a way to do this with regex, which I don't think there is) (and yes, I would like Smith to go to SMITH) – jhpratt Jul 17 '15 at 02:48
  • @user2718801 What is a “word” in your case? If someone’s name is “Herbert-McIntosh” should it become “HERBERT-MCINTOSH” (as one word) or “HERBERT-McINTOSH” (as two words)? – Sebastian Simon Jul 17 '15 at 02:51
  • For this purpose, a word is anything delimited by a space (so the latter of the two). However, a case like this will likely never show up (and if it does, so be it), so it doesn't much matter. – jhpratt Jul 17 '15 at 02:56
  • Ok, I added another section for replacing multiple instances. – Sebastian Simon Jul 17 '15 at 03:03
  • That's an excellent solution! Much simpler than what I was trying to do (if the pattern is found, then break by newline, check each for the pattern again, then concatenate multiple times). This got implemented smoothly. I can't think of anything wrong (or further additions), so I'm happy to say the problem has been solved completely! Thanks a ton @Xufox – jhpratt Jul 17 '15 at 03:11
  • No problem! The alternative form “HERBERT-MCINTOSH” can’t be easily done, anyway, as the function will convert it to “Herbert-McINTOSH” because, well… it follows the pattern… – Sebastian Simon Jul 17 '15 at 03:12
  • That's what I prefer anyway, I just didn't know if it would match by default – jhpratt Jul 17 '15 at 03:17