score:1

you could use a captured variable.

item result = items.firstordefault();
items.foreach(x =>
{
  if(result.id < x.id)
    result = x;
});

score:3

try this:

var maxid = from i in items
            group i by i.clientid int g
            select new { id = g.max(i=>i.id }

score:3

in linq you can solve it the following way:

item itemmax = (from i in items
     let maxid = items.max(m => m.id)
     where i.id == maxid
     select i).firstordefault();

score:5

or you can write your own extension method:

static partial class extensions
{
    public static t wheremax<t, u>(this ienumerable<t> items, func<t, u> selector)
    {
        if (!items.any())
        {
            throw new invalidoperationexception("empty input sequence");
        }

        var comparer = comparer<u>.default;
        t   maxitem  = items.first();
        u   maxvalue = selector(maxitem);

        foreach (t item in items.skip(1))
        {
            // get the value of the item and compare it to the current max.
            u value = selector(item);
            if (comparer.compare(value, maxvalue) > 0)
            {
                maxvalue = value;
                maxitem  = item;
            }
        }

        return maxitem;
    }
}

score:6

in case you don't want to use morelinq and want to get linear time, you can also use aggregate:

var maxitem = 
  items.aggregate(
    new { max = int32.minvalue, item = (item)null },
    (state, el) => (el.id > state.max) 
      ? new { max = el.id, item = el } : state).item;

this remembers the current maximal element (item) and the current maximal value (item) in an anonymous type. then you just pick the item property. this is indeed a bit ugly and you could wrap it into maxby extension method to get the same thing as with morelinq:

public static t maxby(this ienumerable<t> items, func<t, int> f) {
  return items.aggregate(
    new { max = int32.minvalue, item = default(t) },
    (state, el) => {
      var current = f(el.id);
      if (current > state.max) 
        return new { max = current, item = el };
      else 
        return state; 
    }).item;
}

score:10

this is an extension method derived from @seattle leonard 's answer:

 public static t getmax<t,u>(this ienumerable<t> data, func<t,u> f) where u:icomparable
 {
     return data.aggregate((i1, i2) => f(i1).compareto(f(i2))>0 ? i1 : i2);
 }

score:34

use maxby from the morelinq project:

items.maxby(i => i.id);

score:40

int max = items.max(i => i.id);
var item = items.first(x => x.id == max);

this assumes there are elements in the items collection of course.

score:101

.orderbydescending(i=>i.id).first()

regarding the performance concern, it is very likely that this method is theoretically slower than a linear approach. however, in reality, most of the time we are not dealing with the data set that is big enough to make any difference.

if performance is a main concern, seattle leonard's answer should give you linear time complexity. alternatively, you may also consider to start with a different data structure that returns the max value item at constant time.

first() will do the same as take(1) but returns the item directly instead of an enumeration containing the item.

score:201

this will loop through only once.

item biggest = items.aggregate((i1,i2) => i1.id > i2.id ? i1 : i2);

thanks nick - here's the proof

class program
{
    static void main(string[] args)
    {
        ienumerable<item> items1 = new list<item>()
        {
            new item(){ clientid = 1, id = 1},
            new item(){ clientid = 2, id = 2},
            new item(){ clientid = 3, id = 3},
            new item(){ clientid = 4, id = 4},
        };
        item biggest1 = items1.aggregate((i1, i2) => i1.id > i2.id ? i1 : i2);

        console.writeline(biggest1.id);
        console.readkey();
    }


}

public class item
{
    public int clientid { get; set; }
    public int id { get; set; }
}  

rearrange the list and get the same result


Related Query

More Query from same tag