views:

894

answers:

6

For the following datatable column, what is the fastest way to get the min and max values?

AccountLevel  
0  
1  
2  
3 
A: 

select MIN(AccountLevel) AS 'min' from tableName

Is that what you're asking? Your questions is pretty googlable, btw.

http://www.w3schools.com/sql/sql_func_min.asp

portland
He's not using SQL.
SLaks
The question should be specified more precisely, especially when tags are "datatable", "select".
portland
No, the tags are pretty precise, when put into the context of the other ones: C# and .NET
Jay Stevens
A: 
SELECT MIN(AccountLevel) AS 'min', MAX(AccountLevel) AS 'max' FROM table;

That covers the "max", too.

lajuette
He's not using SQL.
SLaks
+1  A: 

The most efficient way to do this (believe it or not) is to make two variables and write a for loop.

SLaks
+3  A: 

Use LINQ. It works just fine on datatables, as long as you convert the rows collection to an IEnumerable.

List<int> levels = AccountTable.AsEnumerable().Select(al => al.Field<int>("AccountLevel")).Distinct().ToList();
int min = levels.Min();
int max = levels.Max();

Edited to fix syntax; it's tricky when using LINQ on DataTables, and aggregating functions are fun, too.

Yes, it can be done with one query, but you will need to generate a list of results, then use .Min() and .Max() as aggregating functions in separate statements.

Cylon Cat
But it requires two iterations.
SLaks
Does this code work properly?
Ahmed
Code fixed. This is a bit tricky to do off the top of the head. Sorry.
Cylon Cat
One more fix; you can add .Distinct() when creating the list, to minimize the work of searching for min and max.
Cylon Cat
One or two more code fixes. Sorry; I'm really rusty on LINQ syntax this morning. I think I've caught all the bugs now.
Cylon Cat
Somehow I don't think that `Distinct` will speed this up - it has to hash every element, whereas `Min` and `Max` just do a compare.
Aaronaught
Well, that's a good, simple performance test to run.
Cylon Cat
+4  A: 
int minAccountLevel = int.MinValue;
int maxAccountLevel = int.MaxValue;
foreach (DataRow dr in table.Rows)
{
    int accountLevel = dr.Field<int>("AccountLevel");
    minAccountLevel = Math.Min(minAccountLevel, accountLevel);
    maxAccountLevel = Math.Max(maxAccountLevel, accountLevel);
}

Yes, this really is the fastest way. Using the Linq Min and Max extensions will always be slower because you have to iterate twice. You could potentially use Linq Aggregate, but the syntax isn't going to be much prettier than this already is.

Aaronaught
Yes, this is what SLaks suggests, to use for loop as the fastest way.
Ahmed
Yes, but I think it should be { int accountLevel = dr.Field<int>("AccountLevel"); min = Math.Min(min, accountLevel); max = Math.Max(max, accountLevel);}isn't it?
Ahmed
@Ahmed: Sorry, typo in the variable assignments. Fixed.
Aaronaught
+1  A: 
var answer = accountTable.Aggregate(new { Min = int.MinValue, Max = int.MaxValue }, 
                                        (a, b) => new { Min = Math.Min(a.Min, b.Field<int>("AccountLevel")),
                                                        Max = Math.Max(a.Max, b.Field<int>("AccountLevel")) });
int min = answer.Min;
int max = answer.Max;

1 iteration, linq style :)

chaowman