繁体   English   中英

使用 LINQ 查找最小值和最大值

[英]Finding Min and Max using LINQ

我正在尝试创建一个 LINQ 查询,允许用户从我网页上的下拉列表中选择“最小值”或“最大值”。 如果用户选择 Min 它将显示具有最低报价的记录(报价来自名为 rentals 的数据库表)

我对 .Min() 和 .Max() 没有任何好感。 我不确定如何解决这个问题,因此我们将不胜感激。

这是我的 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();
            }
        }
    }
}

这是我的 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>

出租类:

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

让我们看下面的示例(这是您的实时代码

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

注意:在 0、1、2 范围内更改option值以测试您的案例。

只要您确定_context.Rentals中有数据,您在else中的最后一个示例应该可以返回 max Quote 我不确定你为什么使用Async Task但你没有等待UserInput == 1else中的任何内容,只有UserInput == 0

这应该工作

var Rentals = (from s in _context.Rentals select s.Quote).Max();

示例(在此处测试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
    }
}

我不确定您的应用程序的其余部分是什么样子或它是如何使用的,但是是的,您可以随意调用您的方法。 您只想要Quote十进制值,还是与之关联的整个Rental 要根据您向我们展示的内容更改您的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;
    }
}

未经测试,但你可以这样做:

        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();

这个想法是您按RentalID对其进行分组以获得 Max/Min Quote ,然后获取具有这些RentalIDQuote的第一条记录

如果他们有相同的报价并且您想显示所有记录而不是第一个:

        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();

正如其他人提到的,您需要使用.Select(s => s.Quote).Min() (或.Max )。 但是,您的select列表选项没有任何值。 您需要指定适当的值,例如:

<option value="0">All</option>
<option value="1">Min</option>
<option value="2">Max</option>

我认为部分问题在于您仅在UserInput == 0的情况下分配Rental 在其他情况下添加分配应该使您的结果在用户更改输入时更新。

此外,听起来您想获取所有具有最大(或最小) Quote的对象的完整记录。 如果是这种情况,那么OrderByGroupBy方法应该在这里有所帮助,因为它们允许您根据数据的属性对数据进行排序,例如Quote的值,并将具有相同值的数据分组在一起。

例如:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM