0

I need sort letters from file as alphabet. How can i do this? I need ToString method. Now console prints:

ABCDEFGIJKLM...ĄČĖĮ...

I need to get this:

AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ

Thanks

  static char[] Letters(string e) // 
    {
        e = e.ToUpper();

        char[] mas = new char[32];
        int n = 0;
        foreach (char r in e)
            if (Array.IndexOf(mas, r) < 0)
                if (Char.IsLetter(r))
                    mas[n++] = r;
        Array.Resize(ref mas, n);
        Array.Sort(mas);
        return mas;
    }
Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
Mantas
  • 83
  • 1
  • 7

2 Answers2

0

You could use following method to remove diacritics:

static string RemoveDiacritics(string text)
{
    var normalizedString = text.Normalize(NormalizationForm.FormD);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

Then you can use those chars for the ordering:

string e = "ABCDEFGIJKLM...ĄČĖĮ...";
var normalizedCharList = e.Zip(RemoveDiacritics(e), (chr, n) => new { chr, normValue = (int)n }).ToList();
var orderedChars = normalizedCharList.OrderBy(x => x.normValue).Select(x => x.chr);
string ordered = new String(orderedChars.ToArray());
Community
  • 1
  • 1
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
0

You can solve this by sorting the characters using a comparer that understands how to compare characters alphabetically (the default is ordinal comparison).

This implementation is very inefficient, because it converts chars to strings every time it does a compare, but it works:

public class CharComparer : IComparer<char>
{
    readonly CultureInfo culture;

    public CharComparer(CultureInfo culture)
    {
        this.culture = culture;
    }

    public int Compare(char x, char y)
    {
        return string.Compare(new string(x, 1), 0, new string(y, 1), 0, 1, false, culture);
    }
}

(Note: The culture is not actually necessary here; it works without it. I just included it for completeness.)

Then you can use that with sort functions that accept anIComparer, such as Array.Sort():

static void Main()
{
    var test = "AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ".ToCharArray();
    Console.OutputEncoding = System.Text.Encoding.Unicode;

    Array.Sort(test);
    Console.WriteLine(new string(test)); // Wrong result using default char comparer.

    Array.Sort(test, new CharComparer(CultureInfo.GetCultureInfo("lt")));  // Right result using string comparer.
    Console.WriteLine(new string(test));
}

An alternative approach is to use an array of single-character strings rather than an array of chars, and sort that instead. This works because the sort functions will use the string comparer, which understands alphabetical order:

var test = "AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ".Select(x => new string(x, 1)).ToArray();
Console.OutputEncoding = System.Text.Encoding.Unicode;

Array.Sort(test); // Correct result because it uses the string comparer, which understands alphabetical order.
Console.WriteLine(string.Concat(test)); 

Or using Linq:

var test = "AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ".Select(x => new string(x, 1)).ToArray();
Console.OutputEncoding = System.Text.Encoding.Unicode;

// Correct result because it uses the string comparer, which understands alphabetical order.
test = test.OrderBy(x => x).ToArray();
Console.WriteLine(string.Concat(test)); 

Using an array of strings instead of an array of chars is probably more performant when sorting like this.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276