-1

There is the following code, it has a function that finds the letters in word in its middle (1 or 2 characters) and makes them capital, and then outputs.

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(test("Rofl"));
        Console.WriteLine(test("Camel"));
        Console.WriteLine(test("R"));
    }

    public static String test(string value) {
        return value.Length % 2 == 0 
            ? value.Substring(value.Length / 2 - 1, 2).ToUpper()
            : value.Substring(value.Length / 2, 1).ToUpper();
    }
}

Tell me, please, how do I make it so that the word was completely derived, but the letters from the middle were completely replaced by capital letters?

It is necessary that it be so:

ROFl
CaMel
R
panoskarajohn
  • 1,846
  • 1
  • 21
  • 37
Octavian
  • 155
  • 8

3 Answers3

3

Something like this? Not the cleanest of ways.

public static string test(string value)
{
    if(string.IsNullOrEmpty(value)) return value;
    var array = value.ToCharArray();
    if (value.Length % 2 == 0)
    {
        array[value.Length / 2 - 1] = Char.ToUpper(array[value.Length / 2 - 1]);
        array[value.Length / 2] = Char.ToUpper(array[value.Length / 2]);
    }
    else
    {
        array[value.Length / 2] = Char.ToUpper(value[value.Length / 2]);
    }
    return new string(array);
}
panoskarajohn
  • 1,846
  • 1
  • 21
  • 37
  • 1
    Watch out for dividing by 0. Currently empty string will throw exception. – GrayCat Dec 28 '19 at 21:53
  • 1
    This works, but note that it performs two allocations, first in `ToCharArray`, then in `new string`. – V0ldek Dec 28 '19 at 21:55
  • @V0ldek String builder is not always faster it has been pointed out recently to me. Nor that more memory efficient for small strings. -> https://stackoverflow.com/questions/21078/most-efficient-way-to-concatenate-strings#comment93328343_12257751. `Also check this` -> https://www.meziantou.net/performance-string-concatenation-vs-string-format-vs-interpolated-string.htm – panoskarajohn Dec 28 '19 at 22:00
  • 1
    @panoskarajohn It does put less pressure on the garbage collector, but it only comes in play if this code is on a hot path. Optimisation should always come as a result of profiling an issue, so I'm just pointing out that there's room for improvement, if it's needed. You'd probably get the most efficiency out of the new `string.Create` that takes a `SpanAction`. – V0ldek Dec 29 '19 at 01:03
1

You can do the transformation with the LINQ Select overload that works on pairs element-index.

public string MiddleLettersToUpper(string s)
{
    IEnumerable<char> transformed;
    if (s.Length % 2 == 0)
    {
        transformed = s.Select((c, i) => 
            i == s.Length / 2 || i == s.Length / 2 - 1 ? char.ToUpper(c) : c);
    }
    else
    {
        transformed = s.Select((c, i) => 
            i == s.Length / 2 ? char.ToUpper(c) : c);
    }

    return string.Concat(transformed);
}

It's pretty performant, because string.Concat uses a StringBuilder underneath, so you only do one pass through the string and allocate one string for the result.

DISCLAIMER: This code doesn't care about the culture when using ToUpper, so it's not suitable for production (there's also no argument validation, but that's obvious).

V0ldek
  • 9,623
  • 1
  • 26
  • 57
0

You can do it with regular expression:

    public static string test(string value)
    {
        value = value ?? string.Empty;
        int half = value.Length % 2 == 0 ? (value.Length / 2) - 1: (value.Length / 2);
        Regex r = new Regex("(?<=^.{"+ half + "})[a-zA-Z]{1,2}(?=.{"+ half + "}$)");
        var match = r.Match(value);
        if (match != null)
        {
            var result = r.Replace(value, match.ToString().ToUpper());
            return result;
        }
        return value;
    }

First we found the half count of letters (the count of letter in the bigging and the end not to uppaer)

Regular expression explains:

find start of a line (^) + any charecter (.) half count ({half}) but don't take them (Positive precedes Lookahead ?<=)

then find one or two charecters ({1,2}) in abc ([a-zA-Z]) - this is the match

and on the end find any charecter (.) half count ({half}) + end of a line ($) but again don't take them (Positive follows Lookahead ?=).

You can test this regex here : regex101

s-s
  • 382
  • 2
  • 12