3

Has anyone got a tidier way of doing this with linq to entities?

I am trying to get the item in each group that has the highest X, Y or Z e.g. Max( X, Y, Z )

var points = from g in groupedData
             from ep in g
             where (ep.X > ep.Y ?
                               ep.X > ep.Z ? ep.X : ep.Z
                             : ep.Y > ep.Z ? ep.Y : ep.Z)
             == g.Max(e => e.X > e.Y ?
                           e.X > e.Z ? e.X : e.Z
                             : e.Y > e.Z ? e.Y : e.Z)
             select ep;
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Void
  • 265
  • 1
  • 3
  • 11
  • possible duplicate of [In c# is there a method to find the max of 3 numbers?](http://stackoverflow.com/questions/6800838/in-c-sharp-is-there-a-method-to-find-the-max-of-3-numbers) – mellamokb Feb 28 '13 at 16:07
  • @mellamokbTheWise : don't agree, we need a solution compatible with Linq2Sql or Linq2Entities ! – JYL Feb 28 '13 at 16:14

3 Answers3

3
var points = from g in groupedData
             let gMax = g.Max(e => e.X > e.Y ?
                                    (e.X > e.Z ? e.X : e.Z)
                                  : (e.Y > e.Z ? e.Y : e.Z))
             from ep in g
             where ep.X == gMax
                   || ep.Y == gMax
                   || ep.Z == gMax
             select ep;

PS : Linq2SQL or Linq2Entities ? Because you flagged "EF" !

Edit : I've just tested this with success :

var points = from g in groupedData
             let gMax = g.Max(e => new int[] { e.X, e.Y, e.Z }.Max())
             from ep in g
             where ep.X == gMax
                   || ep.Y == gMax
                   || ep.Z == gMax
             select ep;

Do you confirm it works in your case ?

JYL
  • 8,228
  • 5
  • 39
  • 63
  • 1
    I was hoping to get rid of all the question marks and colons. +1 though for introducing me to 'let'. – Void Feb 28 '13 at 16:33
  • Yes that works, it also works to use the 'Enumerable.Max()' for the where clause which I think makes it more obvious what is happening. On one hand though it does mean this question was answered at least in part by mellamokbTheWise's duplicate question. – Void Mar 01 '13 at 08:48
0

i would create an Extension Method to handle it

public static int Max(params int[] a)
{
    return a.Max();
}

or something along those lines

you would then use it like

var largestNumber = Max(1,2,3,4,5);

or

Max(ep.X,ep.Y,ep.Z) == Max(e.X,e.Y,e.Z)
RoughPlace
  • 1,111
  • 1
  • 13
  • 23
  • It's not about Linq2Objects here, but Linq2Sql or Linq2Entities (Void should be more precise). Extension methods work only in Linq2Object. – JYL Feb 28 '13 at 16:22
  • Apologies for the lack of precision but this is for ling to entities – Void Feb 28 '13 at 16:28
0

If you really want to get rid of the question marks and colons you can try this:

var points = from g in groupedData
         from ep in g
         select ep).OrderByDescending(x => x.GetType().GetProperties().Max(y => y.GetValue(x,null))).FirstOrDefault());

Explanation:

This basically uses reflection to get the list of properties in the Item (in your case X, Y and Z) and then order the items based on the Max between the properties. Then select the first one from the list which should be the item with the highest property.

The positive side of this is that if you decide to add one more property (lets say K) you wont have to change anything. (Immagine what you would have to do if you want to also add K to the comparison you had with the question marks and colons).

Note: If you have other properties in your class that you dont want to use in the comparison you can add replace x.GetType().GetProperties() by

x.GetType().GetProperties().Select(prop =>prop.PropertyType.Name.Equals("Int32"))

This would only get the integer properties. Use only if you need it or else ignore.

hope that helped

Y2theZ
  • 10,162
  • 38
  • 131
  • 200