[英]Finding Min and Max using LINQ
I am trying to create a LINQ query that allows the user to select Either Min Or Max from a drop down that I have on my web page.我正在尝试创建一个 LINQ 查询,允许用户从我网页上的下拉列表中选择“最小值”或“最大值”。 If the user selects Min it will display the record with the lowest Quote (Quote coming from a database table called rentals)
如果用户选择 Min 它将显示具有最低报价的记录(报价来自名为 rentals 的数据库表)
I have not had any luck with.Min() and.Max().我对 .Min() 和 .Max() 没有任何好感。 I am not sure how to go about this so any help would be appreciated.
我不确定如何解决这个问题,因此我们将不胜感激。
This is my if statement for deciding what option the user has chosen on the drop down box:这是我的 if 语句,用于确定用户在下拉框中选择的选项:
namespace CarGarageSales.Pages.Queries
{
[BindProperties]
public class Query3Model : PageModel
{
private readonly CarGarageSales.Data.CarGarageSalesContext _context;
public IList<Rental> Rental { get; set; }
[BindProperty(SupportsGet = true)]
public int UserInput { get; set; }
public Query3Model(CarGarageSales.Data.CarGarageSalesContext context)
{
_context = context;
}
public async Task OnGetAsync()
{
if (UserInput == 0)
{
var Rentals = (from s in _context.Rentals
select s);
Rental = await Rentals.ToListAsync();
}
else if (UserInput == 1)
{
var Rentals = (from s in _context.Rentals
select s).Min();
}
else
{
var Rentals = (from s in _context.Rentals
select s.Quote).Max();
}
}
}
}
This is my HTML section:这是我的 HTML 部分:
@page
@model CarGarageSales.Pages.Queries.Query3Model
@{
ViewData["Title"] = "Query3";
}
<h2>Query3</h2>
<form>
<p>
Min or Max?:<select asp-for="UserInput">
<option></option>
<option>Min</option>
<option>Max</option>
</select>
<input type="submit" value="Search" />
</p>
</form>
<p class="Text">Here is the record for the Rentals you requested!</p>
<table class="table Text">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Rental[0].RentalID)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Duration)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Quote)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Rental)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.RentalID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Duration)
</td>
<td>
@Html.DisplayFor(modelItem => item.Quote)
</td>
</tr>
}
</tbody>
</table>
Rentals class:出租类:
namespace CarGarageSales.Models
{
[BindProperties]
public class Rental
{
[Required]
public int RentalID { get; set; }
[Required]
[Display(Name = "Price")]
[Range(100, 200000, ErrorMessage = "Price must be between 100 and 200,000 Pounds")]
public decimal Price { get; set; }
[Required]
[Display(Name = "Duration")]
[Range(1, 36,ErrorMessage = "Duration must be between 1 and 36 Months")]
public int Duration { get; set; }
[Required]
[Display(Name = "Quote")]
[Range(20, 10000, ErrorMessage = "Quote must be between 20 and 10000 Pounds")]
public decimal Quote { get; set; }
public Customer Customer { get; set; }
public virtual IList<Car> Cars { get; set; }
public virtual IList<SalesManRental> SalesManRental { get; set; }
}
}
Let's see an example below ( Here is your live code )让我们看下面的示例(这是您的实时代码)
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var option = 1;
var list = new[]{ new Rental{ RentalID = 1, Quote = 1 }, new Rental{ RentalID = 2, Quote = 2 }, new Rental{ RentalID = 3, Quote = 3 }, new Rental{ RentalID = 4, Quote = 1 }, new Rental{ RentalID = 5, Quote = 3 } };
var minQuote = list.Min((p => p.Quote));
var maxQuote = list.Max((p => p.Quote));
var result = list.Where(p => (option == 1 && p.Quote == minQuote) || (option == 2 && p.Quote == maxQuote));
if(option == 0)
result = list;
foreach(var item in result)
Console.WriteLine(item.Quote);
}
public class Rental
{
public int RentalID { get; set; }
public decimal Price { get; set; }
public decimal Quote { get; set; }
}
}
Note: Change value of option
in range 0, 1, 2 to test your case.注意:在 0、1、2 范围内更改
option
值以测试您的案例。
You last example within the else
should work to return the max Quote
, as long as you are sure have data in _context.Rentals
.只要您确定
_context.Rentals
中有数据,您在else
中的最后一个示例应该可以返回 max Quote
。 I am not sure why you are using Async Task
but you are not awaiting anything within UserInput == 1
or the else
, only UserInput == 0
我不确定你为什么使用
Async Task
但你没有等待UserInput == 1
或else
中的任何内容,只有UserInput == 0
This should work这应该工作
var Rentals = (from s in _context.Rentals select s.Quote).Max();
Example (test it here https://dotnetfiddle.net/2SnPcS )示例(在此处测试https://dotnetfiddle.net/2SnPcS )
using System;
using System.Collections.Generic;
using System.Linq;
public class Program {
public class Rental
{
public int RentalID { get; set; }
public decimal Price { get; set; }
public int Duration { get; set; }
public decimal Quote { get; set; }
}
public static void Main()
{
// sample data
var rentals = new List<Rental> {
new Rental { RentalID = 1, Price = 100.00m, Duration = 2, Quote = 200.00m },
new Rental { RentalID = 2, Price = 100.00m, Duration = 2, Quote = 200.00m },
new Rental { RentalID = 3, Price = 100.00m, Duration = 1, Quote = 100.00m },
new Rental { RentalID = 4, Price = 100.00m, Duration = 1, Quote = 100.00m },
new Rental { RentalID = 5, Price = 100.00m, Duration = 5, Quote = 500.00m }
};
// get min quote
var minQuote = (from s in rentals select s.Quote).Min();
// get max quote
var maxQuote = (from s in rentals select s.Quote).Max();
Console.WriteLine(string.Format("min={0} max={1}", minQuote, maxQuote));
// Outputs: min=100.00 max=500.00
}
}
I am not sure what the rest of your application looks like or how it is being used, but yes you can call your methods anything you want.我不确定您的应用程序的其余部分是什么样子或它是如何使用的,但是是的,您可以随意调用您的方法。 Do you want just the
Quote
decimal value, or the entire Rental
associated with it?您只想要
Quote
十进制值,还是与之关联的整个Rental
? To change your OnGetAsync
method based on what you showed us, getting the decimal value only, it would look something like this (you were almost there).要根据您向我们展示的内容更改您的
OnGetAsync
方法,仅获取十进制值,它看起来像这样(您几乎就在那里)。
public decimal GetQuoteAmount()
{
// this could be min
if (UserInput == 0)
{
return (from s in _context.Rentals select s.Quote).Min();
}
// this could be max
else if (UserInput == 1)
{
return (from s in _context.Rentals select s.Quote).Max();
}
else
{
// is there a third option? What do you want to happen if they do not select Min or Max?
return 0;
}
}
Not tested, but you could do something like this:未经测试,但你可以这样做:
var filteredRentals = _context.Rentals.GroupBy(g => g.RentalID)
.Select(x => new Rental
{
RentalID = x.Key,
Quote = x.Max(z => z.Quote),
Duration = x.FirstOrDefault(r => r.RentalID == x.Key && r.Quote == x.Max(z => z.Quote)).Duration,
Price = x.FirstOrDefault(r => r.RentalID == x.Key && r.Quote == x.Max(z => z.Quote)).Price
}).ToList();
The idea is you group it by RentalID
to get the Max/Min Quote
, then get the first record that has those RentalID
and Quote
这个想法是您按
RentalID
对其进行分组以获得 Max/Min Quote
,然后获取具有这些RentalID
和Quote
的第一条记录
In case they have same quote and you want to show all records instead of the first:如果他们有相同的报价并且您想显示所有记录而不是第一个:
var groupedRentals = _context.Rentals.GroupBy(g => g.RentalID)
.Select(x => new
{
RentalID = x.Key,
Quote = x.Max(z => z.Quote)
}).ToList();
var filteredGroupedRentals = _context.Rentals.Where(r => groupedRentals.Any(g =>
g.RentalID == r.RentalID &&
g.Quote == r.Quote))
.ToList();
As others have mentioned, you'll need to use .Select(s => s.Quote).Min()
(or .Max
).正如其他人提到的,您需要使用
.Select(s => s.Quote).Min()
(或.Max
)。 However, your select
list options don't have any values.但是,您的
select
列表选项没有任何值。 You need to specify the appropriate values, such as:您需要指定适当的值,例如:
<option value="0">All</option>
<option value="1">Min</option>
<option value="2">Max</option>
I think part of the problem is that you only assign Rental
in the case where UserInput == 0
.我认为部分问题在于您仅在
UserInput == 0
的情况下分配Rental
。 Adding an assignment in the other cases should make your results update when the user changes their input.在其他情况下添加分配应该使您的结果在用户更改输入时更新。
Additionally, it sounds like you want to get the full records of all the objects with the largest (or smallest) Quote
.此外,听起来您想获取所有具有最大(或最小)
Quote
的对象的完整记录。 If this is the case, then the OrderBy
and GroupBy
methods should help here because they allow you to sort the data based on it's properties, like the value of Quote
, and group data with the same value together.如果是这种情况,那么
OrderBy
和GroupBy
方法应该在这里有所帮助,因为它们允许您根据数据的属性对数据进行排序,例如Quote
的值,并将具有相同值的数据分组在一起。
For example:例如:
public async Task OnGetAsync()
{
if (UserInput == 0)
{
Rental = _context.Rentals().ToListAsync();
}
else if (UserInput == 1)
{
// Get the group of items with min quote
Rental = _context.Rentals()
.GroupBy(r => r.Quote) // Group items with the same quote (Quote becomes the Key)
.OrderBy(g => g.Key) // Order the groups by quote (smallest will be first)
.FirstOrDefault() // Choose the first group (those with min quote)
.ToListAsync(); // Select the items into a list
}
else
{
// Get the group of items with max quote
Rental = _context.Rentals()
.GroupBy(r => r.Quote) // Group items with the same quote (Quote becomes the Key)
.OrderBy(g => g.Key) // Order the groups by quote (smallest will be first)
.LastOrDefault() // Choose the last group (those with max quote)
.ToListAsync(); // Select the items into a list
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.