26

I have an array of strings of variable length. Currently I have a loop that iterates through the array to find the longest string in array. Is there any way I could use LINQ to write it in more efficient and / or cleaner way?

Brandon Moretz
  • 6,863
  • 3
  • 28
  • 41
vrrathod
  • 1,130
  • 2
  • 16
  • 27

6 Answers6

53

It won't be much more efficient, however it would be a bit cleaner to do something like:

var strings = new string[] { "1", "02", "003", "0004", "00005" };

string longest = strings.OrderByDescending( s => s.Length ).First();

Output: 00005

Brandon Moretz
  • 6,863
  • 3
  • 28
  • 41
  • great! thanks, I have used FirstOrDefault(). It sure looks cleaner, but is there any advantage on performance side? – vrrathod Jun 29 '11 at 17:07
  • @vrrathod There is no performance gain, it's still doing the same iterative logic you had, it's just a more concise syntax, which is what LINQ is all about. – Brandon Moretz Jun 29 '11 at 17:09
  • It sure does the same thing. Here is how I tested. I generated an array of 5000 strings. LINQ takes about 15 cpu ticks on my machine. I wrote an old fashioned loop that compares length of strings. It returns in 0 ticks. The diff i guess is for sorting. – vrrathod Jun 29 '11 at 17:36
16
strings.Aggregate(string.Empty, (seed, f) => f?.Length ?? 0 > seed.Length ? f : seed);

Aggregate syntax is slightly harder to read than the other methods, but strictly speaking it's more efficient than the other approaches I see here as it doesn't require sorting. Just an O(N) implementation.

EDIT: This approach, along with most of the others here assumes there are no null values in your list, lest f.Length throw a null ref exception. A quick ternary operator (f != null ? f.Length : 0) would fix that if it were a valid for your enumerable.

EDIT (2.5 years later): Null coalesce is better than ternary null check.

Caleb Holt
  • 176
  • 1
  • 5
  • I prefer this answer as it indeed answers the question asked *and* i believe it is the most efficient for a single item answer when a whole list of the longest words is not needed *and* with the additional edit, Caleb mentions handling null strings too. Two thumbs up from me! For convenience: here's the code i tested that works well: `string longest = strings.Aggregate(string.Empty, (seed, f) => (f == null ? 0 : f.Length) > seed.Length ? f : seed);' – Shawn Kovac Jun 06 '17 at 18:03
9
string [] strings;
return strings.OrderByDescending (s => s.Length).First ();
agent-j
  • 25,367
  • 5
  • 47
  • 76
2

Even though this is an old question I'd like to add that the most efficient answer is not provided. It isn't a one liner, but it's the fastest and returns a collection of the longest strings, which OrderBy or Aggregate doesn't provide. Matt Ellen was the closest with his answer, but using Max within his Where makes it rather slow when you're working with a large collection.

The correct answer should be:

int maxLength = collection.Max(x => x.Length);
string[] longestStrings = collection.Where(x => x.Length == maxLength).ToArray();

Consider using the ?. (in C# 6.0) and ?? operators to check for null values if your collection can contain these.

anthonytimmers
  • 236
  • 1
  • 7
  • 1
    correction: the question asks for one string not a list of the longest strings. also your code needs a `.ToArray()' before that last semicolon to compile. But i do commend you on providing code that can easily be used to provide either a list of the longest words or just the first word, with a simple '.FirstOrDefault()' vs '.ToArray()' at the end of your code. Personally i prefer the flexibility of this solution, so i most like what your solution provides. Thanks! – Shawn Kovac Jun 06 '17 at 17:54
2
string[] arr = new string[] { "a", "aa", "aaa" };

var longest = arr.Where(s => s.Length == arr.Max(m => m.Length)).First();

output aaa

This way the code is clearly getting you the string with the max length.

Matt Ellen
  • 9,933
  • 4
  • 61
  • 80
  • this sure works. But its of O(N^2), so it would take a little longer than the other answer. For Ex. on 5000 string array `strings.OrderByDescending( s => s.Length ).First();` would return in about 15 CPU ticks on my machine, while this would take about 390. ticks. – vrrathod Jun 29 '11 at 17:31
  • Yes, I realise this. I put it up because it states what it is doing, rather than using a side effect of ordering. – Matt Ellen Jun 29 '11 at 17:33
0

I don't have a compiler right now but this will also work.

string[] arr = new string[] { "a", "aa", "aaa" };
var longest = arr.Max(w => w.Length)
dee-see
  • 21,841
  • 5
  • 54
  • 87
Umut Koseali
  • 854
  • 13
  • 20