3

I have a generic List of Policy objects.

The list contains the following data

id  policyNumber   policySequence  otherData
1   101            1               aaaa
2   101            2               bbbb
3   101            3               cccc
4   102            1               dddd
5   103            1               eeee
6   103            2               ffff

I want to select the one row containing the highest policySequence for each policyNumber, so that I end up with the following:

id  policyNumber   policySequence  created
3   101            3               cccc
4   102            1               dddd
6   103            2               ffff

I have a solution below using a foreach, but was wondering if there was an easier, cleaner way to do this in LINQ?

class Program
    {
        static void Main(string[] args)
        {
            List<Policy> policyList = new List<Policy>
                                          {
                                              new Policy {id = 1, policyNumber = 101, policySequence = 1, otherData = "aaaa"},
                                              new Policy {id = 2, policyNumber = 101, policySequence = 2, otherData = "bbbb"},
                                              new Policy {id = 3, policyNumber = 101, policySequence = 3, otherData = "cccc"},
                                              new Policy {id = 4, policyNumber = 102, policySequence = 1, otherData = "dddd"},
                                              new Policy {id = 5, policyNumber = 103, policySequence = 1, otherData = "eeee"},
                                              new Policy {id = 6, policyNumber = 103, policySequence = 2, otherData = "ffff"}
                                          };

            List<Policy> filteredPolicyList = new List<Policy>();

            foreach(var policy in policyList)
            {
                if(!filteredPolicyList.Exists(x => x.policyNumber == policy.policyNumber))
                {
                    filteredPolicyList.Add(policy);
                }
                else
                {
                    var currentPolicyInFilteredList = filteredPolicyList.Where(x => x.policyNumber == policy.policyNumber).First();

                    if (policy.policySequence > currentPolicyInFilteredList.policySequence)
                    {
                        filteredPolicyList.Remove(currentPolicyInFilteredList);
                        filteredPolicyList.Add(policy);
                    }
                }
            }
        }
    }

    public class Policy
    {
        public int id;
        public int policyNumber;
        public int policySequence;
        public string otherData;
    }
Rezler
  • 1,064
  • 1
  • 8
  • 21

3 Answers3

6
var maxPolicies = policyList
    .GroupBy(p => p.PolicyNumber)
    .Select(grp => grp.OrderByDescending(p => p.PolicySequence).First());
Lee
  • 142,018
  • 20
  • 234
  • 287
  • 2
    A note for those that find this question. if you want to group by multiple criteria http://stackoverflow.com/questions/5231845/c-sharp-linq-group-by-on-multiple-columns .GroupBy(p => new { p.criteria, p.criteria1, p.criteria2, }) – DFTR Oct 03 '13 at 19:29
2

If you're using LINQ to Objects, you could use the MoreLINQ project's DistinctBy method:

var maxPolicies = policyList.OrderByDescending(x => x.PolicySequence)
                            .DistinctBy(x => x.PolicyNumber);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

You could group and aggregate:

var result = from p in policyList
             group p by p.policyNumber into g
             select new { Policy = g.Key, Max = g.Max() };
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928