LINQ GroupBy string PagePath

Viewed 58

I have a list of entries List<StatisticsData>

 public class StatisticsData
{
    public Guid Id { get; set; }   
    public string PagePath { get; set; }    
    public DateTime Date { get; set; }
}

Sample values:

    94F0F2FF-D251-46AA-8AF4-E1CE14A70DFF | osahori.com.pr | 2020-02-18 
    1697C57B-BD10-43A2-B0F8-EDDFD289AB9B | osahori.com.pr/clientes | 2020-02-18 
    E91C049A-2F63-4B2E-87BD-B41284332614 | osahori.com.pr/faco-seu-orcamento | 2020-02-18 
    E91C049A-2F63-4B2E-87BD-B41284332614 | tc.onsiege.com/ | 2020-02-18 
    BF596A54-C9FF-4FE4-8881-3C1BBCA6C3A6 | tc.onsiege.com/home | 2020-02-18
    5D32AF13-B7F9-40BB-927C-C07C5AC994FF | www.ubertaxi.com.br | 2020-02-18 
    17B5925F-8EFD-4DE1-BC56-4CB1241D0EF1 | www.ubertaxi.com.br/clients | 2020-02-18
    ...

In result I need groups for the same context of PagePath, e.g:

First group:

    94F0F2FF-D251-46AA-8AF4-E1CE14A70DFF | osahori.com.pr | 2020-02-18 
    1697C57B-BD10-43A2-B0F8-EDDFD289AB9B | osahori.com.pr/clientes | 2020-02-18 
    E91C049A-2F63-4B2E-87BD-B41284332614 | osahori.com.pr/faco-seu-orcamento | 2020-02-18 

Second group:

   E91C049A-2F63-4B2E-87BD-B41284332614 | tc.onsiege.com/ | 2020-02-18 
   BF596A54-C9FF-4FE4-8881-3C1BBCA6C3A6 | tc.onsiege.com/home | 2020-02-18

Third:

    5D32AF13-B7F9-40BB-927C-C07C5AC994FF | www.ubertaxi.com.br | 2020-02-18 
    17B5925F-8EFD-4DE1-BC56-4CB1241D0EF1 | www.ubertaxi.com.br/clients | 2020-02-18

Etc.

Is it possible to do with LINQ?

3 Answers

Demo on dotnet fiddle

You can GroupBy the exact path only, like osahori.com.pr, tc.onsiege.com by using Subtring like below.

Note that: Check the case PagePath has no "/".

    var result = list.GroupBy(p => 
                {
                    var indexOf = p.PagePath.IndexOf('/');
                    return indexOf > 0 ? p.PagePath.Substring(0, indexOf) : p.PagePath;
                });

    foreach(var item in result)
    {
        Console.WriteLine("Group: " + item.Key);
        foreach(var item2 in item.ToList())
        {
            Console.WriteLine(item2.Id + "|" + item2.PagePath + "|" + item2.Date);
        }
    }

Output

Group: osahori.com.pr
94F0F2FF-D251-46AA-8AF4-E1CE14A70DFF|osahori.com.pr|2/18/2020 12:00:00 AM
1697C57B-BD10-43A2-B0F8-EDDFD289AB9B|osahori.com.pr/clientes|1/1/0001 12:00:00 AM
E91C049A-2F63-4B2E-87BD-B41284332614|osahori.com.pr/faco-seu-orcamento|1/1/0001 12:00:00 AM
Group: tc.onsiege.com
E91C049A-2F63-4B2E-87BD-B41284332614|tc.onsiege.com/|2/18/2020 12:00:00 AM
BF596A54-C9FF-4FE4-8881-3C1BBCA6C3A6|tc.onsiege.com/home|2/18/2020 12:00:00 AM
Group: www.ubertaxi.com.br
5D32AF13-B7F9-40BB-927C-C07C5AC994FF|www.ubertaxi.com.br|2/18/2020 12:00:00 AM
17B5925F-8EFD-4DE1-BC56-4CB1241D0EF1|www.ubertaxi.com.br/clients|1/1/0001 12:00:00 AM

Yes, quite easily:

var grouped = listStatisticsData
  .GroupBy(sd => sd.PagePath.Substring(0, sd.PagePath.IndexOf('/')));

It will group by part of PagePath until first occurence of /. Keys will be automatically stored as result of sd.PagePath.IndexOf('/')

Well, given a PagePath we should GroupBy either by entire PagePath if it doesn't contain / (e.g. osahori.com.pr) or by the prefix before first / (say, osahori.com.pr for osahori.com.pr/clientes):

 var result = listStatisticsData
   .GroupBy(item => {
      int p = item.PagePath.IndexOf('/');

      return p < 0 ? item.PagePath : item.PagePath.Substring(0, p);  
    })
Related