5

What is the best way to create acronym from upper letters in C#?

Example:

Alfa_BetaGameDelta_Epsilon

Expected result:

ABGDE

My solution works, but it's not nice

        var classNameAbbreviationRegex = new Regex("[A-Z]+", RegexOptions.Compiled);
        var matches = classNameAbbreviationRegex.Matches(enumTypeName);
        var letters = new string[matches.Count];

        for (var i = 0; i < matches.Count; i++)
        {
            letters[i] = matches[i].Value;
        }

        var abbreviation = string.Join(string.Empty, letters);
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
Rudis
  • 1,177
  • 15
  • 30
  • You can accept only one answer. I saw that you first accepted Tyler's answer and now mine. If you like multiple answers, accept the answer that you actually end up using. – Daniel Hilgarth Aug 08 '13 at 12:33

6 Answers6

5
string.Join("", s.Where(x => char.IsUpper(x))
Sayse
  • 42,633
  • 14
  • 77
  • 146
5
string.Join("", s.Where(char.IsUpper));
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • Sorry, you're right. However, string.Empty is preferred over "", ;P – BartoszKP Aug 08 '13 at 12:21
  • 1
    @BartoszKP I think string.Empty vs. "" is a matter of personal preference – Tyler Aug 08 '13 at 12:22
  • 1
    @BartoszKP: `string.Empty` is not prefered over `""`, that's just a coding guideline. There's no difference between the two. – Steven Aug 08 '13 at 12:22
  • 1
    I prefer `""` because its easier to type – Sayse Aug 08 '13 at 12:24
  • Thanks, this is much better solution than my – Rudis Aug 08 '13 at 12:25
  • I'm sorry, I referred to the incorrect `Join` overload, the actual overload used is [String.Join(string, IEnumerable)](http://msdn.microsoft.com/en-us/library/dd992421.aspx) which is available since .NET 4.0. – Steven Aug 08 '13 at 12:27
  • 2
    But I think that the use of `Concat` is more intuitive than `Join` in this case. – Steven Aug 08 '13 at 12:28
  • @Steven: I actually think the overload you first posted is being used. It directly matches the return type of `Where`. – Daniel Hilgarth Aug 08 '13 at 12:28
  • @DanielHilgarth: No, `String.Join` is used. I checked this in VS. – Steven Aug 08 '13 at 12:30
  • @Steven: Sorry, you are correct. `Where` returns `IEnumerable`, not `IEnumerable`. – Daniel Hilgarth Aug 08 '13 at 12:36
  • @DanielHilgarth: Correctamundo :-) – Steven Aug 08 '13 at 12:39
  • @Steven And exactly because such a coding guideline exists, string.Empty is preferred. It's not a guideline just for sake of being a guideline. I'm not arguing that using "" is incorrect - it's just more readable to use constants then hard-coded strings. – BartoszKP Aug 08 '13 at 12:57
  • 1
    @BartoszKP: There are several guidelines. Some force the use of `string.Empty`, others force the use of `""`. None if better, as long as you are consistent within the code base. – Steven Aug 08 '13 at 13:09
  • @Steven Could you provide a source with any guideline that forces usage of ""? I understand that it may be a strongly subjective topic, however for me it seems obvious that constants improve readability over hard-coded strings. – BartoszKP Aug 08 '13 at 13:56
5
string test = "Alfa_BetaGameDelta_Epsilon";
string result = string.Concat(test.Where(char.IsUpper));
Tyler
  • 578
  • 3
  • 10
3

You can use the Where method to filter out the upper case characters, and the Char.IsUpper method can be used as a delegate directly without a lambda expression. You can create the resulting string from an array of characters:

string abbreviation = new String(enumTypeName.Where(Char.IsUpper).ToArray());
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
3

By using MORE regexes :-)

var ac = string.Join(string.Empty, 
                     Regex.Match("Alfa_BetaGameDelta_Epsilon", 
                                 "(?:([A-Z]+)(?:[^A-Z]*))*")
                          .Groups[1]
                          .Captures
                          .Cast<Capture>()
                          .Select(p => p.Value));

More regexes are always the solution, expecially with LINQ! :-)

The regex puts all the [A-Z] in capture group 1 (because all the other () are non-capturing group (?:)) and "skips" all the non [A-Z] ([^A-Z]) by putting them in a non-capturing group. This is done 0-infinite times by the last *. Then a little LINQ to select the value of each capture .Select(p => p.Value) and the string.Join to join them.

Note that this isn't Unicode friendly... ÀÈÌÒÙ will be ignored. A better regex would use @"(?:(\p{Lu}+)(?:[^\p{Lu}]*))*" where \p{Lu} is the Unicode category UppercaseLetter.

(yes, this is useless... The other methods that use LINQ + IsUpper are better :-) but the whole example was built just to show the problems of Regexes with Unicode)

MUCH EASIER:

var ac = Regex.Replace("Alfa_BetaGameDelta_Epsilon", @"[^\p{Lu}]", string.Empty);

simply remove all the non-uppercase letters :-)

xanatos
  • 109,618
  • 12
  • 197
  • 280
2
var str = "Alfa_BetaGammaDelta_Epsilon";
var abbreviation = string.Join(string.Empty, str.Where(c => c.IsUpper()));
BartoszKP
  • 34,786
  • 15
  • 102
  • 130