Как я могу найти максимальное значение в List в .Net 2.0?

#c# #.net

#c# #.net

Вопрос:

Я хочу найти максимальное значение из объектов списка.Структура класса

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

Теперь у меня есть функция для нахождения максимальной высоты сайта.Сигнатура функции такова

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

Я использую цикл for для определения максимального значения и сталкиваюсь с проблемой производительности….
.Net framework 2.0 — я использую прямо сейчас

Кто-нибудь может сказать мне, как найти максимальную высоту без использования цикла for? возможно ли это?

Комментарии:

1. Поскольку вы говорите, что не можете использовать цикл for, это звучит как домашнее задание. Пометьте это как домашнее задание, если это так.

2. Поскольку я сталкиваюсь с проблемой производительности при использовании цикла foreach, я опубликовал этот вопрос — Rajesh Kumar G

3. @Rajesh: было бы нормально использовать цикл while вместо цикла for, или какой-либо тип циклической конструкции не разрешен?

4. С какой проблемой производительности вы столкнулись? Сложность поиска Max в одномерном несортированном массиве имеет линейный порядок O(N) .

5. @Matt : Возможно ли найти максимальное значение с помощью делегирования? если нет, опубликуйте ответ с помощью цикла while

Ответ №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;
    }
}
  

С помощью списка 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;
    }
  

Комментарии:

1. Итак, как это быстрее, чем цикл?

2. возможно ли выполнить приведенный выше ответ для List<T> ?

3. yeah..it это несколько быстрее, чем цикл for … я доволен

4. @alexl : ты там? возможно ли выполнить приведенный выше ответ для List<T>?

5. Что вы подразумеваете под List<T>, вы должны реализовать интерфейс, чтобы знать, как будет выглядеть T, если вы хотите выполнить сортировку по нему…

Ответ №2:

Это довольно странный способ сделать это, но вы могли бы сделать это с помощью рекурсии.

Вы бы создали свою начальную функцию 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 с текущим значением максимальной высоты, и как только вы дойдете до конца списка, вы сможете вернуть любое максимальное значение.

Комментарии:

1. C # не имеет TCO. Я уже слышу, как CLR говорит «Исключение переполнения стека».

2. @GregC: Только если список действительно длинный. Но да, я определенно не стал бы решать проблему таким образом, потому что в реальном мире я могу использовать LINQ или циклы.

Ответ №3:

Самым простым решением было бы выполнить итерацию по списку с использованием цикла for и проверить максимальную высоту отдельных записей.

Другим возможным решением было бы реализовать интерфейс IComparable и отсортировать список всех элементов в соответствии с его высотой. Первым элементом в списке после сортировки является тот, который вы ищете.

Для более продвинутого решения вы также могли бы использовать метод Find в указанном списке и указать делегат, который определит элемент с максимальной высотой.

Надеюсь, это поможет.

Комментарии:

1. 1. Да, это в основном то, что я собирался сказать. Это было бы более полным решением с кратким разделом кода, содержащим Как: , в котором используется небольшой фрагмент кода alexl , приведенный выше.

Ответ №4:

Как сказал GregC, оптимизация зависит от вашего общего случая. Если список довольно статичен и в него не часто добавляются элементы, вы можете отсортировать список при вставке. Это переключает вставку с O (1) на сложность вашего алгоритма сортировки (существует несколько алгоритмов O (n log n)) и извлечение из O (n) в O (1). Как использовать List<T>.Sort()

Я предпочитаю хранить его в списке, а не в словаре, потому что метод dictionary добавляет хэш-коду дополнительный смысл, которого большинство людей не ожидают. Где, как уже есть встроенные методы сортировки списка, которые стандартизированы, и многие люди сразу узнают.

Комментарии:

1. Ссылка, которую вы разместили, — это сортировка класса «string». как я могу отсортировать список на основе свойства класса?

2. Вы бы предоставили анонимный делегат или функцию в метод Sort(), который позволяет вам сравнивать каждое из значений. Вы могли бы сказать -1, если меньше, 1, если больше, 0, если равно.

3. Это будет выполняться намного медленнее, чем dictionary, поскольку вам пришлось бы полностью сортировать каждую вставку.

4. @GregC: можете ли вы, пожалуйста, опубликовать код с помощью delegate?… Я изменил возвращаемый тип свойства … это моя ошибка … я неправильно ввел…

5. @RajeshKumarG: Именно это используется в примере, но если вы прочтете страницу, вы увидите, что она использует IComparable<T> .

Ответ №5:

Я бы добавил объекты в словарь, что позволило бы мне быстрее сортировать по высоте.

Во всех классических контейнерах существует компромисс между скоростью вставки и скоростью извлечения.

Эта стратегия имеет смысл, когда обновления редки, но вы часто полагаетесь на максимальное значение.

Вам нужно было бы переопределить GetHashCode(), чтобы возвращать меньшие числа с большей высотой.

Я вижу небольшую трудность в том, что у вас будут дубликаты, если ваш GetHashCode () реализован таким образом. Вам нужно будет выбрать точность и не вставлять дубликаты в свою коллекцию на основе этого факта.

В качестве альтернативы я бы использовал MultiDictionary из PowerCollections, а затем полагался бы на шаблон линейного поиска для нескольких показаний, которые находятся в самой верхней ячейке.

 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. в thi 2.0 .NET нет LINQ

2. @GregC: Я отредактировал свой вопрос сейчас … пожалуйста, проверьте это … также я упомянул саму версию фреймворка, о которой идет речь

3. Вы пишете, а я могу помочь вам в процессе, когда вы застреваете.

4. @GregC: С помощью делегирования это невозможно?

5. GetHashCode() фактически является делегатом для словаря, который использует siteData в качестве ключа.

Ответ №6:

вы можете использовать этот максимальный метод msdn Max

если этот метод отсутствует в .Net 2.0, я думаю, его лучше использовать для

Ответ №7:

Это невозможно без цикла, если у вас нет kwnoledge о порядке последовательности ввода. Покажите нам свой код поиска по максимальному значению, возможно, возможна оптимизация?

Ответ №8:

Если вы хотите пропустить только 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 со значением 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;
        }
  

но я не знаю, будет ли у него производительность лучше, чем у цикла for. Я буду их сокращать, но было бы приятно узнать, насколько велик или хотя бы приблизительное количество siteData, которое будет иметь ваш список!