Reputation: 693
I would like to know If It's possible to create a "one-line" Linq to retrieve longest string value of specific Datatable column, meaning that all column data (numbers, dates,strings...) should be converted to string and then return longest string.
What I've found is only how to obtain longest string from a List, or max length value.
This is what I tried so far (error in Length):
string maxString = dt
.AsEnumerable()
.Select(row => row[mycolumn].ToString())
.Where(s => s.OrderByDescending(st => st.Length).First());
Upvotes: 11
Views: 3227
Reputation: 37299
You are almost there:
string maxString = dt.AsEnumerable()
.Select(row => row[mycolumn].ToString())
.OrderByDescending(st => st.Length).FirstOrDefault();
A Where
expects a predicate (function that will return true or false). Instead just order the projection (the .Select
) as you did and retrieve the first item.
Notice that is is an O(nlogn)
solution which can be improved to an O(n)
solution by not sorting but by finding the item with the max length. One possible way of doing so is an in Dimitry's answer. For less than huge collections I'm not sure one would really feel the difference but it is indeed worth noticing this.
See that you can also use MoreLinq's .MaxBy
that can be added through Nuget (For the GitHub repo) which will both give you the O(n)
performance and the desired "one-liner":
var row = dt.AsEnumerable().MaxBy(r => r[mycolumn].ToString().Length);
Upvotes: 10
Reputation: 186678
You are looking for ArgMax
- a value such that it has max value of some kind of property. Standard Linq doesn't provide ArgMax
but you can implement it via Aggregate
(i.e. get a single value from a sequence):
string maxString = dt
.AsEnumerable()
.Select(row => row[mycolumn].ToString())
.Aggregate((s, a) => a.Length > s.Length ? a : s);
Upvotes: 16
Reputation: 186
First of all do not use AsEnumerable
right after dt.
.
Write somehow like this:
dt.OrderByDescending(row => row[mycolumn].Length).First();
Upvotes: 3