2012-06-11 4 views
3

Быстрый и, вероятно, легко Lambda вопрос:Lambda Max и Max и Max

У меня есть ресторан с отзывами. Я хочу запросить один с:

  • Max (AverageRating)
  • и МАХ (ReviewCount)
  • и МАХ (NewestReviewDate)
  • И Мин (DistanceAway)

Что-то вроде этого:

var _Result = AllRestaurants 
    .Max(x => x.AverageRating) 
    .AndMax(x => x.ReviewCount) 
    .AndMax(x => x.NewestReviewDate) 
    .AndMin(x => x.DistanceAway); 

Теперь я знаю, что это псевдокод. Но это прекрасно описывает это!

Конечно, в нескольких заявлениях это просто.

Просто интересно, возможно ли это в одном заявлении, не убивая читаемость.

Заранее спасибо. Я знаю, что некоторые из вас любят вопросы по запросу!

+1

вопрос остается неясным. Каждый из пяти запросов, о которых вы упомянули, может вернуть другой ресторан. Нет смысла комбинировать запросы таким образом. – Odrade

+4

И что должно содержать результат? Один ресторан, который имеет наилучшее сочетание всех критериев или 4 разных ресторана, по одному для каждого критерия? Обратите внимание, что вы должны подробно объяснять, потому что каждый вариант нужно будет уточнить более подробно. – Servy

ответ

6

Вы не можете иметь несколько максимальных или минимальных значений, что не имеет смысла. Вам нужно какое-то эвристики как:

.Max(x => x.AverageRating * x.ReviewCount - x.DaysSinceLastReview - x.DistanceAway) 
+3

Если это вообще то, что вы имеете в виду, вы, скорее всего, захотите указать веса для каждого критерия. – Servy

+0

Точно. Вам понадобится вес, чтобы настроить его, чтобы вернуть ответ, который вы хотите. – IngisKahn

+1

@SteveWortham Оба являются законными возможностями, поэтому я просто спросил OP, а не предполагал, что он означает тот или иной. – Servy

6

Возможно, это будет делать?

var bestRestaurant = AllRestaurants 
    .OrderByDescending(r => r.AverageRating) 
    .ThenByDescending(r => r.ReviewCount) 
    .ThenByDescending(r => r.NewestReviewCount) 
    .ThenBy(r => r.DistanceAway) 
    .FirstOrDefault(); 

Вам нужно будет изменить порядок выступлений, чтобы отразить, что является самым важным.

+0

Вместо этого вы можете использовать 'FirstOrDefault', чтобы избежать возможного' InvalidOperationException', когда последовательность пуста. –

+0

Yup, отредактированный, чтобы включить его – Richard

0

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

var HighestRating = AllRestaurants.Max(x => x.AverageRating); 
var HighestReviewCount = AllRestaurants.Max(x => x.ReviewCount); 
var LatestReviewDate = AllRestaurants.Max(x => x.NewestReviewDate); 
var ShortestDistanceAway = AllRestaurants.Min(x => x.DistanceAway); 

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

0

Рассмотрим что-то вроде этого ...

List<RestaurantRecord> _Restaurants; 

public RestaurantRecord Best() 
{ 
    return _Restaurants.Where(
       x => 
        x.AverageRating >= _BestRating && 
        x.ReviewCount >= _MinReviews && 
        x.Distance <= _MaxDistance) 
         .GetFirstOrDefault(); 
} 

При этом, используя лямбда в этом случае будет иметь последствия ремонтопригодности вниз по дороге. Было бы неплохо реорганизовать это, так что если в будущем появятся другие критерии (например: доступ к смартфонам? Тип кухни?), Ваше приложение может быть легко изменено, чтобы адаптироваться к ним.

На этой ноте, немного лучше, реализация может быть что-то вроде:

public RestaurantRecord Best() 
{ 
    IQueryable temp = _Restaurants.Clone(); 

    temp = temp.Where(x => x.AverageRating >= _BestRating); 
    temp = temp.Where(x => x.ReviewCount >= _MinReviews); 
    // ...snip... 

    return temp.GetFirstOrDefault(); 
} 

Я надеюсь, что это ставит вас на правильном пути. :)

1

Альтернативой тому, чтобы иметь некоторую взвешенную эвристику, - это заказать AverageRating, затем ReviewCount, затем ...

Что-то, как это должно работать:

var _Result = AllRestaurants 
    .OrderByDescending(x => x.AverageRating) 
    .ThenByDescending(x => x.ReviewCount) 
    .ThenByDescending(x => x.NewestReviewDate) 
    .ThenByDescending(x => x.DistanceAway); 
    // using *Descending so you get the higer-valued ones first 
+0

Похоже на [подход Ричарда] (http://stackoverflow.com/a/10986444/284240), кроме того, что вы предпочитаете дальнейшие рестораны;) –

+0

Может быть, мне нравятся хорошие длинные диски? Хороший улов! –