1

I would like to replace one character in a string with an uppercase of the same character. Is there an elegant way to do this? Eg I have 'Donald Mcdonald' and I would like to uppercase the first 'd' in 'Mcdonald' so I end up with 'McDonald'

The string.replace function only gives the option to replace first or all. If I use the code below it obviously won't work.

if(name.containsIgnoreCase(' mc')){
    integer mc = name.indexOfIgnoreCase(' mc') + 3;
    name = name.replaceFirst(name.mid(mc, 1), name.mid(mc,1).toUpperCase());
}

2 Answers 2

2

Apex doesn't really support that. Strings are as in Java, immutable objects, so you can only create modified copies, but not update the original. It has to do with Java's String Pool. So, replaceFirst is probably appropriate in your case. Notably, the first parameter is actually a regular expression, so you can target exactly what you want to with some practice.

For example:

String name = 'old mcdonald';
String mc = '(?i)( mcd)';
name = name.replaceFirst(mc, ' McD');

You can also use String.split with similar effect, although this is probably the easiest way to get what you're looking for.

If you don't know what you're looking for, the following may also help:

Pattern mcprefix = Pattern.compile('(?i)( ma?c)(i|d|k)');
Matcher m = matcher.match(name);
while(m.find()) {
  String g1 = m.group(1), g2 = m.group(2);
  name = name.replaceFirst(mc, g1.capitalize()+g2.captialize());
}

Which should give you a pretty good algorithm to start from.

4
  • Thing is I don't know what comes after the 'mc' - could be 'mcintyre', 'mckenzie' etc, so I have to get the char after the mc, capitalise it and then do the replaceFirst I guess. Need to sort out names are are entered in all lower or uppercase to be titlecase, but to cater for these anomalies as best possible (mc, mac)
    – Irene
    Commented Jul 21, 2020 at 1:34
  • @Irene I see. You could use Pattern.match to determine the letter, then use that instead. I'll edit.
    – sfdcfox
    Commented Jul 21, 2020 at 2:23
  • I got an error but managed to fix it (2nd line: Matcher m = mcprefix.matcher(name); ) I changed the regex too and am using this now: (?i)( ?ma?c)(\p{L}) so it'll catch whatever alpha character is after the mc/mac, but I don't know how many matches there are, and I don't think there's a way I can loop through them, is there? So if my string is 'mckenzie mcewan macdonald' I'd have 3 matches. I suppose I'd have to split the string and sort each one out and then join them again?
    – Irene
    Commented Jul 21, 2020 at 2:57
  • I posted my final code - am happy for you to edit yours with this and then I can credit you with the solution.
    – Irene
    Commented Jul 21, 2020 at 3:25
0

Thanks to @sfdcfox for the platform to build on. This is what I eventually ended up with which works perfectly for a string with multiple occurrences.

Pattern mcprefix = Pattern.compile('(?i)( ?ma?c)(\\p{L}+|\\P{L}+)');
list<string> names = name.split(' ');
list<string> fixednames = new list<string>();
for(string n : names){
    Matcher m2 = mcprefix.matcher(n);
    while(m2.find()) {
      String g1 = m2.group(1), g2 = m2.group(2);
      Integer start = n.indexOf(g1 + g2);
      if (start == 0 || n.substring(start - 1, start).isWhitespace())
        n = n.replaceFirst(g1 + g2, g1 + g2.capitalize());
    }
    fixednames.add(n);
}
name = String.join(fixednames, ' ');

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .