如何在.Net 2.0中找到List <t>中的最大值?</t>

时间:2011-05-06 11:51:27

标签: c# .net

我想从List对象中找到最大值。类结构是

         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; }
            }
    }

现在我有了查找Maximum SiteHeight的功能。该功能的签名是

              public double FindMaxHeight(List<SiteData> objSite)
              {
               //logic to find the max. site height
               }

我正在使用for循环来识别最大值并面临性能问题.... .Net framework 2.0 - 我现在正在使用

有人能告诉我如何在不使用for循环的情况下找到最大高度吗?有可能吗?

8 个答案:

答案 0 :(得分:1)

我会将对象添加到字典中,这样我就可以更快地按高度排序。

对于所有经典容器,在插入速率和检索速率之间存在折衷。

当更新很少时,此策略很有意义,但您经常依赖最大值。

您需要覆盖GetHashCode()以返回较大高度的较小数字。

如果以这种方式实现GetHashCode(),我可以看到一点点困难,你将有重复。您需要决定精度,而不是根据这一事实在您的集合中插入重复项。

或者,我会使用PowerCollections中的MultiDictionary,然后依靠线性搜索模式来处理最顶层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?
    }
}

答案 1 :(得分:1)

这是一种奇怪的方式,但你可以用递归来做。

您可以创建初始函数double FindMaxHeight(List<SiteData> objSite)

这需要调用一个递归函数的函数。递归函数是导致自己再次被调用的函数,例如

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;
    }
}

因此,您可以像这样浏览列表,并将(enumerator.Current as SiteData).SiteHeight与您当前获得的最大高度值进行比较,一旦到达列表末尾,您就可以返回最大值。

答案 2 :(得分:1)

正如GregC所说,优化取决于您的常见情况。如果列表是相当静态的并且没有经常添加项目,则可以在插入时对列表进行排序。这将O(1)的插入转换为排序算法的复杂性(有许多O(n log n)算法)并从O(n)到O(1)的检索。 How to use List<T>.Sort()

我更喜欢将它保存在列表而不是字典中,因为字典方法为哈希码增加了额外的含义,这是大多数人不会期望的。其中已有内置方法对标准化列表进行排序,很多人会立即知道。

答案 3 :(得分:1)

最简单的解决方案是使用for循环迭代列表并检查各个条目的最大高度。

另一种可能的解决方案是实现IComparable接口,并根据其高度对所有项目的列表进行排序。排序后列表中的第一项是您要查找的项目。

对于更高级的解决方案,您还可以在指定列表中使用Find方法,并指定将确定具有最大高度的项目的委托。

希望它有所帮助。

答案 4 :(得分:1)

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;
    }
}

使用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;
    }

答案 5 :(得分:0)

您可以使用此Max方法msdn Max

如果2.0 .Net中没有此方法,我认为最好用于

答案 6 :(得分:0)

如果您不了解输入序列的顺序,那么没有循环是不可能的。 向我们展示您的最大值搜索代码,也许可以进行优化?

答案 7 :(得分:0)

如果您只想跳过for,可以使用以下方法:

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;
        }

或者这个,如果可以有SiteData withoud siteHeight值

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;
        }

但我不知道它是否会有更好的性能。我会告诉他们,但很高兴知道你的清单会有多大或至少大小的SiteData数量!