4

I have a List<> which contains several strings. For example {a1, a2, a15, a3, a16, a1}. I want to get the string with the Max number (a16). I tried using Where() and Max() but then it will return the maximum value (16), where I want to return the string (a16). I guess I could do it with an additional Where() and contains() but I was wondering if I could do it in a simpler way.

Here is the code example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace linq_example
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string> {"b1", "a1", "a2","a9", "a16", "a1", "a5" , "b20"};
            var max = list.Where(i => i.IndexOf("a") != -1).Max(a => Convert.ToInt32(a.Substring(1)));
            Console.WriteLine(max.ToString());
            Console.ReadLine();
        }
    }
}

This program will print 16 where I wanted to print a16

  • Is it a typo that the list in your example actually does not contain `a16` but contains `16`? If you have strings in a `List` then LINQ will not magically convert them to `ints`. You should be getting the `string` which has the "maximum" value (check out sorting rules for strings). – odyss-jii Dec 12 '13 at 11:59
  • It sounds like you're almost there. If you post your code, it will probably be very easy to fix. – Baldrick Dec 12 '13 at 12:00

3 Answers3

2
var biggest = list.OrderByDescending(x => Convert.ToInt32(a.Substring(1)).First();

Note that LINQ OrderBy is "lazily" evaluated. It will pick only first element and won't sort completetly the list. Overhead is comparable to Max(). That's the beauty of LINQ.

Alternatively, you can take a look at this link: LINQ: How to perform .Max() on a property of all objects in a collection and return the object with maximum value

MoreLINQ has MaxBy() that will allow you to do it easily.

Community
  • 1
  • 1
Erti-Chris Eelmaa
  • 22,879
  • 5
  • 54
  • 76
1

Try this:

add these namespaces:

using System.Linq;
using System.Text.RegularExpressions; 

You can use regex to get only the part number of string and convert this result to a int, for sample:

var max = list.Max(x => int.Parse(Regex.Match(x, @"\d+")));
Felipe Oriani
  • 35,246
  • 17
  • 121
  • 176
  • You can save one line by using : Max(x => int.Parse(x.Replace("a", string.Empty))) – AlexH Dec 12 '13 at 12:07
  • Maybe I wasn't clear enough... I've added some code sample. Your solution gives the same answer. –  Dec 12 '13 at 12:26
  • @AlexH, It does not ensure that the item on the list if a number, that's the reason I use `Where` and `int.TryParse` to filter before casting to int. – Felipe Oriani Dec 12 '13 at 12:28
  • @FelipeOriani, my remark wasn't clear enough; you can replace the Select with a Max to save one line : (with your edit) var max = list.Max(x => int.Parse(Regex.Match(x, @"\d+"))) – AlexH Dec 12 '13 at 12:41
0

This might help

List<string> list = new List<string> { "a1", "a2", "a15", "a3", "a16", "a1" };
var largest = list.OrderBy(s => int.Parse(Regex.Match(s, @"\d+").ToString())).Last();
Hossain Muctadir
  • 3,410
  • 1
  • 16
  • 32
  • I thought of using this approach but I think it will have some performance penalty since you now need to sort the entire list and not just finding the max value. –  Dec 12 '13 at 12:28
  • Ya that might be true. But, `max` might also do the same thing internally. – Hossain Muctadir Dec 12 '13 at 12:32