Joe H
Joe H

Reputation: 127

How to sort strings by German phonebook alphabet

I am trying to sort a list of strings using the German alphabet's phonebook ordering. In the German alphabet sort, the special characters, or umlauts, are represent by the following:

  1. Ä -> ae
  2. Ö -> oe
  3. Ü -> ue

Therefore, the ascending sort order should end up something like this:

  1. Ad
  2. Ä
  3. Af

I am working in the C# universe and have been using the CultureInfo to create a new string comparer for the sorting. Using this, I get the following order:

  1. Ä
  2. Ad
  3. Af

    List<string> l = new List<string>();
    l.Add("Ad");
    l.Add("Ä");
    l.Add("Af");
    
    var comparer = StringComparer.Create(CultureInfo.CreateSpecificCulture("de"), true);
    var x = l.OrderBy(y => y, comparer);
    
    foreach(var outp in x) {
        Console.WriteLine(outp);
    }
    

Does anyone know how I could do this with a custom comparer or using an existing culture comparer?

Upvotes: 4

Views: 1523

Answers (2)

Eric MSFT
Eric MSFT

Reputation: 3276

The German phonebook sort is an alternate sort and can be activated by using "de-DE_phoneb" as the name instead of using "de".

Upvotes: 5

RedFox
RedFox

Reputation: 455

You can implement your own comparer class which replaces the umlauts before comparing the two strings:

class CustomStringComparer : IComparer<string>
{

    private string ReplaceUmlauts(string germanText)
    {
        var map = new Dictionary<char, string>() {
          { 'ä', "ae" },
          { 'ö', "oe" },
          { 'ü', "ue" },
          { 'Ä', "Ae" },
          { 'Ö', "Oe" },
          { 'Ü', "Ue" },
          { 'ß', "ss" }
        };

        var res = germanText.Aggregate(
                      new StringBuilder(),
                      (sb, c) => map.TryGetValue(c, out var r) ? sb.Append(r) : sb.Append(c)
                      ).ToString();

        return res;
    }

    public int Compare(string x, string y)
    {
        var xWithoutUmlauts = ReplaceUmlauts(x);
        var yWithoutUmlauts = ReplaceUmlauts(y);

        return StringComparer.CurrentCulture.Compare(xWithoutUmlauts, yWithoutUmlauts);
    }
}

Code for replacement from here.

Then you can simply create a new instance of CustomStringComparer and add it as parameter in your .OrderBy call like this:

var x = l.OrderBy(z => z, new CustomStringComparer());

This will result in the desired output of:

  1. Ad
  2. Ä
  3. Af

Upvotes: 2

Related Questions