0

I have this problem with my output of this code which outputs how many times a character in a string is mentioned.

class Program
{
    static void Main(string[] args)
    {
        string str = Console.ReadLine().ToLower();
        string sortedString = String.Concat(str.OrderBy(c => c));

        foreach (char ch in sortedString)
        {
            Console.WriteLine($"{ch} => {str.Count(x => x == ch)}");
        }
    }
}

This is the output I get:

Alabala
a => 4
a => 4
a => 4
a => 4
b => 1
l => 2
l => 2

This is the output I want to get

Alabala
a => 4
b => 1
l => 2

Would appreciate if somebody helps me out.

Noam M
  • 3,156
  • 5
  • 26
  • 41
Thenis
  • 61
  • 1
  • 10
  • It sorts the str string in a alphabetical order. So if the input is "Alabala" is sorts it like this "aaaabll" – Thenis Apr 13 '16 at 11:16

2 Answers2

2

You can do this in single linq like below:

string str =  Console.ReadLine().ToLower();
string sortedString = String.Concat(str.OrderBy(c => c));

var result = sortedString.GroupBy(x => x)
                         .Select(y => string.Format("{0} => {1}", y.Key, y.Count())).ToList();

foreach (var output in result)
{
    Console.WriteLine(output);
}
Nitin
  • 18,344
  • 2
  • 36
  • 53
  • You can simplify the `sortedString` to: `var sortedString = str.OrderBy(c => c);` - there's no need to turn it back into a string. Likewise, you can lost the `ToList()`. – Matthew Watson Apr 13 '16 at 11:19
  • yes :). I just updated on the result part. Rather orderBy can be part of the single linq – Nitin Apr 13 '16 at 11:21
  • 1
    If you want to go mad, you could write: `var result = str.OrderBy(c => c).GroupBy(x => x).Select(y => $"{y.Key} => {y.Count()}");` ;) – Matthew Watson Apr 13 '16 at 11:22
2

You can use combination of ToDictionary(), OrderBy() and Distinct() methods :

        string str = "halleluyah";

        var grouppedChars = str
            .Distinct()       // removes duplicates
            .OrderBy(c => c)  // orders them alphabetically
            .ToDictionary(    // converts to dictionary [string, int]
                c => c,
                c => str.Count(c2 => c2 == c));

        foreach (var group in grouppedChars)
        {
            Console.WriteLine($"{group.Key} => {group.Value}");
        }

        Console.ReadKey();

Output :

a => 2
e => 1
h => 2
l => 3
u => 1
y => 1

P.S. This is better then GroupBy() because you don't really want to keep this chars groupped somewhere but rather keep only count of them.

Method 2, add your own struct with char information :

        struct CharStatistics
        {
           public readonly char @char;
           public readonly int count;

           public CharStatistics(char @char, int count)
           {
              this.@char = @char;
              this.count = count;
           }
        }

In Main method :

        string str = "halleluyah";

        var charsInfo = str
            .OrderBy(c => c)
            .Distinct()
            .Select(c =>
                new CharStatistics(c, str.Count(c2 => c2 == c)));

        foreach (var stats in charsInfo)
        {
            Console.WriteLine($"{stats.@char} => {stats.count}");
        }
Fabjan
  • 13,506
  • 4
  • 25
  • 52