Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. LINQ
  4. Aggregation using Group by in LINQ

Aggregation using Group by in LINQ

Scheduled Pinned Locked Moved LINQ
questioncsharpdatabaselinq
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Pankaj Chamria
    wrote on last edited by
    #1

    Hi, I am trying to run a linq query on a collection and I want the result to contain all the columns in the collection. But those columns that are not unique across a single rows' aggregation should have the value as null. How can i do this? Is there any expression available using which I can return all such columns for a row (apart from the ones participating in aggregation) which are unique for that aggregated row. eg: 1) The Class:

    public class Person
    {
    string Name
    string Sex
    int Age
    }

    1. The collection:

    List<Person> personList

    1. Sample data in collection:

    Name Sex Age

    Rob Male 25
    Bob Male 25
    Kim Female 22
    Debbie Female 22

    var result = from p in personList
    group p by new {p.Sex} into g
    select new {g.Key.Sex, ???????}

    I want to be able to get the anonymous result as follows:

    Sex Age Name

    Male 25(As 25 is unique across Males) Null (As Name is not unique across Males)
    Female 22(As 22 is unique across Females) Null

    Does anyone have a way to be able to do this?

    Pankaj Chamria, Software Programmer.

    G 2 Replies Last reply
    0
    • P Pankaj Chamria

      Hi, I am trying to run a linq query on a collection and I want the result to contain all the columns in the collection. But those columns that are not unique across a single rows' aggregation should have the value as null. How can i do this? Is there any expression available using which I can return all such columns for a row (apart from the ones participating in aggregation) which are unique for that aggregated row. eg: 1) The Class:

      public class Person
      {
      string Name
      string Sex
      int Age
      }

      1. The collection:

      List<Person> personList

      1. Sample data in collection:

      Name Sex Age

      Rob Male 25
      Bob Male 25
      Kim Female 22
      Debbie Female 22

      var result = from p in personList
      group p by new {p.Sex} into g
      select new {g.Key.Sex, ???????}

      I want to be able to get the anonymous result as follows:

      Sex Age Name

      Male 25(As 25 is unique across Males) Null (As Name is not unique across Males)
      Female 22(As 22 is unique across Females) Null

      Does anyone have a way to be able to do this?

      Pankaj Chamria, Software Programmer.

      G Offline
      G Offline
      Gideon Engelberth
      wrote on last edited by
      #2

      This may be difficult to add a lot of properties, but this should work for your specific example.

      Dim groups = From g In (From p In personList _
      Group p By p.City Into Group) _
      Let SingleName As Boolean = (From r In g.Group Select r.Name Distinct).Count <= 1 _
      Let SingleAge As Boolean = (From r In g.Group Select r.Age Distinct).Count <= 1 _
      Select New Person() With {.Sex = g.Sex, _
      .Name = If(SingleName, g.Group.First.Name, Nothing), _
      .Age = If(SingleAge, g.Group.First.Age, Nothing)}
      For Each g In groups
      Console.WriteLine("{0}, {1}, {2}", g.Sex, g.Age, g.Name)
      Next

      1 Reply Last reply
      0
      • P Pankaj Chamria

        Hi, I am trying to run a linq query on a collection and I want the result to contain all the columns in the collection. But those columns that are not unique across a single rows' aggregation should have the value as null. How can i do this? Is there any expression available using which I can return all such columns for a row (apart from the ones participating in aggregation) which are unique for that aggregated row. eg: 1) The Class:

        public class Person
        {
        string Name
        string Sex
        int Age
        }

        1. The collection:

        List<Person> personList

        1. Sample data in collection:

        Name Sex Age

        Rob Male 25
        Bob Male 25
        Kim Female 22
        Debbie Female 22

        var result = from p in personList
        group p by new {p.Sex} into g
        select new {g.Key.Sex, ???????}

        I want to be able to get the anonymous result as follows:

        Sex Age Name

        Male 25(As 25 is unique across Males) Null (As Name is not unique across Males)
        Female 22(As 22 is unique across Females) Null

        Does anyone have a way to be able to do this?

        Pankaj Chamria, Software Programmer.

        G Offline
        G Offline
        Gideon Engelberth
        wrote on last edited by
        #3

        Upon further consideration, I was able to extract the logic for checking properties for the same value within a group into an extension method. This will simplify the query a little bit.

        Dim lcGroups = From g In (From p In personList _
        Group By p.Sex Into Group) _
        Select New Person() With {.Sex = g.Sex, _
        .Name = g.Group.SameOrDefault(Function(p) p.Name), _
        .Age = g.Group.SameOrDefault(Function(p) p.Age)}

        <System.Runtime.CompilerServices.Extension()> _
        Public Function SameOrDefault(Of TInput, TOutput)(ByVal items As IEnumerable(Of TInput), _
        ByVal valueSelector As Func(Of TInput, TOutput)) As TOutput
        Return SameOrDefault(items, valueSelector, EqualityComparer(Of TOutput).Default)
        End Function

        <System.Runtime.CompilerServices.Extension()> _
        Public Function SameOrDefault(Of TInput, TOutput)(ByVal items As IEnumerable(Of TInput), _
        ByVal valueSelector As Func(Of TInput, TOutput), _
        ByVal comparer As IEqualityComparer(Of TOutput)) As TOutput
        If items Is Nothing Then Return Nothing
        If valueSelector Is Nothing Then
        Throw New ArgumentNullException("valueSelector", "A value selector must be provided.")
        End If
        If comparer Is Nothing Then comparer = EqualityComparer(Of TOutput).Default

        Dim result As TOutput = valueSelector(items.First())
        For Each i In items
            If Not comparer.Equals(result, valueSelector(i)) Then Return Nothing
        Next
        Return result
        

        End Function

        The first overload will work for most cases, but if you wanted to compare complex types or use some non-default comparison, such as the magnitude of a vector, the second overload would come in handy.

        P 1 Reply Last reply
        0
        • G Gideon Engelberth

          Upon further consideration, I was able to extract the logic for checking properties for the same value within a group into an extension method. This will simplify the query a little bit.

          Dim lcGroups = From g In (From p In personList _
          Group By p.Sex Into Group) _
          Select New Person() With {.Sex = g.Sex, _
          .Name = g.Group.SameOrDefault(Function(p) p.Name), _
          .Age = g.Group.SameOrDefault(Function(p) p.Age)}

          <System.Runtime.CompilerServices.Extension()> _
          Public Function SameOrDefault(Of TInput, TOutput)(ByVal items As IEnumerable(Of TInput), _
          ByVal valueSelector As Func(Of TInput, TOutput)) As TOutput
          Return SameOrDefault(items, valueSelector, EqualityComparer(Of TOutput).Default)
          End Function

          <System.Runtime.CompilerServices.Extension()> _
          Public Function SameOrDefault(Of TInput, TOutput)(ByVal items As IEnumerable(Of TInput), _
          ByVal valueSelector As Func(Of TInput, TOutput), _
          ByVal comparer As IEqualityComparer(Of TOutput)) As TOutput
          If items Is Nothing Then Return Nothing
          If valueSelector Is Nothing Then
          Throw New ArgumentNullException("valueSelector", "A value selector must be provided.")
          End If
          If comparer Is Nothing Then comparer = EqualityComparer(Of TOutput).Default

          Dim result As TOutput = valueSelector(items.First())
          For Each i In items
              If Not comparer.Equals(result, valueSelector(i)) Then Return Nothing
          Next
          Return result
          

          End Function

          The first overload will work for most cases, but if you wanted to compare complex types or use some non-default comparison, such as the magnitude of a vector, the second overload would come in handy.

          P Offline
          P Offline
          Pankaj Chamria
          wrote on last edited by
          #4

          Thanks a lot for taking time out to post a LINQ query for my requirement. I would try using this after converting it to C#:-)

          Pankaj Chamria, Software Programmer.

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups