Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как выбрать максимальный элемент? 
:(
    Опции темы
Bonus
Дата 30.6.2008, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 4.10.2006

Репутация: нет
Всего: нет



пробую так:
Код

Point maxX = points.Max(p => p.X);

это работает, но возвращаемое значение не Point, а double. Как на выходе получать именно Point (ну или тип который нужен мне)?
PM MAIL   Вверх
HalkaR
Дата 30.6.2008, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пуфыстый назгул
****


Профиль
Группа: Экс. модератор
Сообщений: 2132
Регистрация: 8.12.2002
Где: В Москве

Репутация: нет
Всего: 42



Код

Point maxX = points.Where(p=>p.X==points.Max(p => p.X));

В тупую smile
PM MAIL   Вверх
Bonus
Дата 1.7.2008, 07:13 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 81
Регистрация: 4.10.2006

Репутация: нет
Всего: нет



хм... сработало, спасибо smile
PM MAIL   Вверх
Partizan
Дата 1.7.2008, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 67



HalkaR,  о_О а просто Point maxX = points.Max(p => p.X); недостаточно?


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
HalkaR
Дата 1.7.2008, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пуфыстый назгул
****


Профиль
Группа: Экс. модератор
Сообщений: 2132
Регистрация: 8.12.2002
Где: В Москве

Репутация: нет
Всего: 42



Partizan, так Bonus же сказал, что это возвращает X, а не Point.
PM MAIL   Вверх
Partizan
Дата 1.7.2008, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: нет
Всего: 67



а....понял...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Idsa
Дата 1.7.2008, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 5
Всего: 62



Кстати-кстати. Тут не все так просто. Это один из тонких моментов в LINQ.
Первый вариант решения, который приходит на ум, - забить на LINQ и воспользоваться старым-добрым foreach. В этом случае за O(n) операций можно найти необходимый элемент. Чем не вариант? Да тем, что после LINQ ну очень не хочется писать подобный "низкоуровневый" перебор.
Если говорить о LINQ решениях этой проблемы, то можно, например, отсортировать список по убыванию и взять первый элемент. Естественно, производительность в этом случае не выдерживает никакой критики (O log n операций и куча понапрасну использованной памяти). Если показать такое решение программисту со старой закалкой, его, наверное, инфаркт хватит smile
Второй LINQ-вариант - использовать код, подобный тому, который написал HalkaR. Только вот, честно говоря, меня удивило, что
Цитата(Bonus @  1.7.2008,  11:13 Найти цитируемый пост)
хм... сработало, спасибо smile 

Ведь этот код возвращает не Point, а коллекцию Point'ов. У меня такой код даже не комплируется (Resharper сразу ругается):
Цитата

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Drawing.Point>' to 'System.Drawing.Point'

Кстати в том кусочке кода еще одна ошибка: переменная p объявляется два раза. Такое не скомпилируется. И выражение
Код

points.Max(p => p.X)

надо заменить на что-нибудь вроде
Код

points.Max(p1 => p1.X)

Ну это так, мелочи: HalkaR просто опечатался.
Чтобы заставить этот код делать именно то, что нужно, просто добавляем в конец вызов метода First:
Код

Point point = points.Where(p => p.X == points.Max(p1 => p1.X)).First();

Вот. Теперь компилятор не ругается и получает необходимый результат. Казалось бы, вот оно, счастье smile Ан нет. Если присмотреться, код-то неоптимальный. На первый взгляд кажется, что выполняется 2n операций: сначала находится максимальный X, а потом элемент с этим значением X. Напомню, что классически эта задача решается за n операций (как выше через foreach). На самом деле этот код ведет себя куда хуже. Дело в том, что points.Max выполняется при каждой итерации (ну действительно, откуда LINQ знать, что это значение является константой?! "Нет, сынок, это фантастика" smile ). Таким образом, этот скрипт выполняется при помощи n*n операций. Невероятно, но при некоторых n этот вариант может работать даже медленнее бредового варианта с сортировкой (n*n против n*log(n) ).
Конечно, пофиксить баг под кодовым названием "расчет point.Max при каждой итерации" не составит труда:
Код

int maxX = points.Max(p1 => p1.X);
Point point = points.Where(p => p.X == maxX).First();

Все, что мы сделали, - вынесли вычисление максимального значения X за цикл. Итого, получаем 2*n операций. Лучше, конечно, но все равно попахивает законом дырявых абстракций. Но ведь если проблему нельзя решить "стандартными средствами", никто не запрещает создать свой собственный метод расширения (хвала С# 3.0).
Упрощенная версия будет выглядеть примерно так:
Код

public static Point MaxX(this IEnumerable<Point> source)
{
 if (source == null)
  throw new ArgumentException("Source is null");
 Point result = default(Point);
 foreach (Point point in source)
  if ((point != default(Point)) || (point.X > result.X))
   result = point;
 return result;
}

Используем вот так:
Код

Point point = points.MaxX();

Это заточенный вариант под этот пример. Конечно, лучше создать более унифицированный метод через дженерики, но мне лень smile

Добавлено @ 18:24
Забыл добавить, что вариант с методом расширения выполняется за n операций.

Это сообщение отредактировал(а) Idsa - 7.7.2008, 18:02


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
Idsa
Дата 7.7.2008, 20:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 5
Всего: 62



Метод расширения я немного неправильно написал. Нужно что-нибудь вроде этого:
Код

   public static Point MaxX(this IEnumerable<Point> source)
    {
      if (source == null)
        throw new ArgumentException("Source is null");
      Point result = default(Point);
      bool flag = false;
      foreach (Point point in source)
      {
        if (flag)
          if (point.X > result.X)
            result = point;
        else
        {
          result = point;
          flag = true;
        }
      }
      if (!flag)
        throw new Exception("Source is empty");
      return result;
    }

Этот подход я позаимствовал в Reflector'е smile


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
akizelokro
Дата 9.7.2008, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: нет
Всего: 5



Цитата

Как на выходе получать именно Point (ну или тип который нужен мне)? 


Дружит ли, кстати, DLinq с user-defined типами?

Код

points.Max(p => p.X)


Что вообще здесь пытается сделать автор, вытащить максимальную х-координату или точку максимальной длины? 


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
Idsa
Дата 9.7.2008, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 2086
Регистрация: 5.12.2006
Где: Томск

Репутация: 5
Всего: 62



Цитата(akizelokro @  9.7.2008,  18:52 Найти цитируемый пост)
Что вообще здесь пытается сделать автор, вытащить максимальную х-координату или точку максимальной длины?  

Точку с максимальным X.

Цитата(akizelokro @  9.7.2008,  18:52 Найти цитируемый пост)
Дружит ли, кстати, DLinq с user-defined типами?

Дружит.


--------------------
Мой блог: alexidsa.blogspot.com
PM MAIL ICQ   Вверх
akizelokro
Дата 11.7.2008, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: нет
Всего: 5



Цитата

Дружит.


Спасибо. Ну вот и общий ответ на первый вопрос:

Цитата

Как на выходе получать именно Point (ну или тип который нужен мне)?


А вообще, все приведенные решения в общем случае неоптимальны. Но если автору темы хватает, то и бог с ними smile 


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
PashaPash
Дата 11.7.2008, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



Цитата(akizelokro @  11.7.2008,  10:19 Найти цитируемый пост)
А вообще, все приведенные решения в общем случае неоптимальны. 
Т.е. ты в "общем случае" умеешь находить максимальный элемент быстрее, чем за O(n)? Дэвид Блейн?


--------------------
PM MAIL WWW   Вверх
akizelokro
Дата 11.7.2008, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: нет
Всего: 5



В каждом общем случае не могу. В конкретном общем - может получиться. Например, при частом использовании такой задачи, я бы создал индекс и делал бы выборку по нему (ага).
Предположу даже больше. Решения в общем случае как минимум не быстрее конкретных решений задач с индивидуальной спецификой. Угу?

Это сообщение отредактировал(а) akizelokro - 11.7.2008, 14:16


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
PashaPash
Дата 11.7.2008, 15:08 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 4
Всего: 49



akizelokro, решение в общем случае - это решение задачи на условиях, озвученных топикастером. Как раз "в общем случае" приведенные решения оптимальны. А в частных - ес-но нет. И это не повод писать в каждой теме "решение неоптимально".
Цитата(akizelokro @  11.7.2008,  14:16 Найти цитируемый пост)
Например, при частом использовании такой задачи, я бы создал индекс и делал бы выборку по нему (ага).
А потом оказалось бы что на поддержание индекса уходит больше ресурсов, чем на все выборки. Или что выборки производятся из временных результатов. Твое решение в общем случае неоптимально (с). 

Для задачи "выбрать из IEnumerable<Point> элемент с максимальным значением X" - решение оптимально в общем случае. А все предположения "а если бы задача была не такой, а другой", "а если бы мы решали частный случай, то общее решение было бы не оптимально" к решению вообще никакого отношения не имеют.


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | LINQ (Language-Integrated Query) | Следующая тема »


 




[ Время генерации скрипта: 0.0607 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.