How can I find the Maximum value in List<T> in .Net 2.0?
I want to find the maximum value from the List objects.The class structure is
public class SiteData
{
#region Fields
private double? siteHeight;
private double? siteWidth;
#endregion
#region Properties
public double? SiteHeight
{
get { return siteHeight; }
set { siteHeight = value; }
}
public double? SiteWidth
{
get { return siteWidth; }
set { siteWidth = value; }
}
}
Now i am having the function to find the Maximum SiteHeight.The signature of the function is
public double FindMaxHeight(List<SiteData> objSite)
{
//logic to find the max. site height
}
I am using for loop to identify the maximum value and facing the performance issue.... .Net framework 2.0 - i 开发者_开发知识库am using right now
Can anyone tell me how to find the maximum height without using for loop? is it possible?
public class SiteData
{
private double? siteHeight;
private double? siteWidth;
public double? SiteHeight
{
get { return siteHeight; }
set { siteHeight = value; }
}
public double? SiteWidth
{
get { return siteWidth; }
set { siteWidth = value; }
}
public static double FindMaxHeight(List<SiteData> objSite)
{
objSite.Sort(delegate(SiteData s1, SiteData s2)
{
if (s1.SiteHeight > s2.SiteHeight)
return 1;
if (s1.SiteHeight < s2.SiteHeight)
return -1;
return 0;
});
return objSite[objSite.Count - 1].SiteHeight.Value;
}
}
With List T:
public static double FindMaxHeight<T>(List<T> objSite)
where T : SiteData
{
objSite.Sort(delegate(T s1, T s2)
{
if (s1.SiteHeight > s2.SiteHeight)
return 1;
if (s1.SiteHeight < s2.SiteHeight)
return -1;
return 0;
});
return objSite[objSite.Count - 1].SiteHeight.Value;
}
It's rather a strange way to do it, but you could do it with recursion.
You would create your initial function double FindMaxHeight(List<SiteData> objSite)
This would need to call a function that is a recursive function. A recursive function is one that causes itself to be called again, e.g.
int EnumerableLength(IEnumerable<T> enumerable)
{
IEnumerator<T> enumerator = enumerable.GetEnumerator();
return EnumeratorCount(enumertor, 0);
}
int EnumeratorCount(IEnumerator<T> enumerator, int count)
{
if(enumerator.MoveNext())
{
count++;
return EnumeratorCount(enumerator, count);
}
else
{
return count;
}
}
So you could move through your list like this, and comparing (enumerator.Current as SiteData).SiteHeight
to the max height value you've currently got, and once you reach the end of the list you can return whatever the max is.
The simplest solution would be iterating over the list using a for loop and checking the individual entries for the maximum height.
Another possible solution would be to implement the IComparable interface and sort the list of all items according to its height. The first item in the list after the sorting is the one you are looking for.
For a more advanced solution you could also use the Find method on the specified list and specify a delegate that will determine the item with the maximum height.
Hope it helps.
As GregC said, the optimization depends on what your common case is. If the list is fairly static and does not have item added often, you can sort the list on insertion. This flips insertion from O(1) to the complexity of your sort algorithm (there are a number of O(n log n) algorithms) and retrieval from O(n) to O(1). How to use List<T>.Sort()
I prefer keeping it in a list as opposed to a dictionary because the dictionary method adds extra meaning to the hashcode that most people won't expect. Where as there are already built-in methods to sort a list that are standardized and many people will know immediately.
I'd add objects into a dictionary, that allows me to sort by height faster.
With all classic containers, there is a trade-off between rate of insertion and rate of retrieval.
This strategy makes sense when updates are rare, but you rely on the max value frequently.
You'd need to override GetHashCode() to return smaller numbers with larger heights.
I can see a little difficulty in that you'll have duplicates if your GetHashCode() is implemented that way. You'll need to decide on precision, and not insert duplicates into your collection based on that fact.
Alternately, I'd use MultiDictionary from PowerCollections, and then rely on linear search pattern for the few readouts that are in the topmost bin.
internal int IndexForSortingBySiteHeight
{
get
{
if(double.IsNaN(siteHeight) throw new ApplicationException();
return (int)Math.Floor(siteHeight);
}
}
public class ContainerForSortingBySiteHeight
{
private List<SiteData> siteDataItems;
public void Add(SiteData datum)
{
if(datum == null) return;
siteDataItems[datum.IndexForSortingBySiteHeight] = datum;
}
public Max
{
get { return siteDataItems[0]; } // here's why a list won't work! What index should i use?
}
}
you can use this Max method msdn Max
if this method doesn't present in 2.0 .Net I think is better to use for
It's not possible without loop if you have no kwnoledge about order of input sequence. Show us your max value search code, maybe optimization is possible?
If you only want to skip the for you can use the following method:
public double FindMaxHeight(List<SiteData> objSite)
{
objSite.Sort(new Comparison<SiteData>((x, y) => y.SiteHeight.Value.CompareTo(x.SiteHeight.Value)));
return objSite.Count > 0 ? objSite[0].SiteHeight.Value : 0;
}
or this one if there can be SiteData withoud siteHeight value
public double FindMaxHeight(List<SiteData> objSite)
{
objSite.Sort(new Comparison<SiteData>((x, y)
=>
{
int xHeight, yHeight;
yHeight = y.SiteHeight.HasValue ? y.SiteHeight.Value : 0;
xHeight = x.SiteHeight.HasValue ? x.SiteHeight.Value : 0;
return yHeight.CompareTo(xHeight);
}
));
return objSite.Count > 0 ? objSite[0].SiteHeight.Value : 0;
}
but I don't know if it will have better performance that the for loop. I will crono them, but it will be nice to know, how big or at least the approximate number of SiteData that your list will have!
精彩评论