KJai
KJai

Reputation:

GroupBy String and Count in LINQ

I have got a collection. The coll has strings:

Location="Theater=1, Name=regal, Area=Area1"

Location="Theater=34, Name=Karm, Area=Area4445"

and so on. I have to extract just the Name bit from the string. For example, here I have to extract the text 'regal' and group the query. Then display the result as

Name=regal Count 33
Name=Karm  Count 22

I am struggling with the query:

Collection.Location.GroupBy(????);(what to add here)

Which is the most short and precise way to do it?

Upvotes: 5

Views: 6961

Answers (3)

James
James

Reputation: 12796

Here is another LINQ alternative solution with a working example.

static void Main(string[] args)
{
    System.Collections.Generic.List<string> l = new List<string>();
    l.Add("Theater=1, Name=regal, Area=Area"); l.Add("Theater=34, Name=Karm, Area=Area4445");

    foreach (IGrouping<string, string> g in l.GroupBy(r => extractName(r)))
    {
        Console.WriteLine( string.Format("Name= {0} Count {1}", g.Key, g.Count())  );
    }
}
private static string extractName(string dirty)
{
    System.Text.RegularExpressions.Match m =
        System.Text.RegularExpressions.Regex.Match(
        dirty, @"(?<=Name=)[a-zA-Z0-9_ ]+(?=,)");

    return m.Success ? m.Value : "";
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500465

Once you've extracted the string, just group by it and count the results:

var query = from location in locations
            let name = ExtractNameFromLocation(location)
            group 1 by name in grouped
            select new { Name=grouped.Key, Count=grouped.Count() };

That's not particularly efficient, however. It has to do all the grouping before it does any counting. Have a look at this VJ article for an extension method for LINQ to Objects, and this one about Push LINQ which a somewhat different way of looking at LINQ.

EDIT: ExtractNameFromLocation would be the code taken from answers to your other question, e.g.

public static string ExtractNameFromLocation(string location)
{
    var name = (from part in location.Split(',')
                let pair = part.Split('=')
                where pair[0].Trim() == "Name"
                select pair[1].Trim()).FirstOrDefault();
    return name;
}

Upvotes: 2

Christian C. Salvad&#243;
Christian C. Salvad&#243;

Reputation: 827316

Yet another Linq + Regex approach:

string[] Location = {
                        "Theater=2, Name=regal, Area=Area1",
                        "Theater=2, Name=regal, Area=Area1",
                        "Theater=34, Name=Karm, Area=Area4445"
                    };

var test = Location.Select(
                            x => Regex.Match(x, "^.*Name=(.*),.*$")
                                      .Groups[1].Value)
                   .GroupBy(x => x)
                   .Select(x=> new {Name = x.Key, Count = x.Count()});

Query result for tested strings

Upvotes: 12

Related Questions