【问题标题】:List of numbers lowest value first, and then by input date首先列出最低值的数字,然后按输入日期
【发布时间】:2021-08-17 10:05:08
【问题描述】:

所以我有一个来自数据库的价格列表。我想对其进行排序,以便列表中的第一个条目是编号最小的条目。然后所有其他条目按输入日期排序。 如何做到这一点?

这是我的代码,一团糟,抱歉我正在尝试:)

            var itemPriceDate = itemPrice.OrderBy(d => d.Invoice.DateInvoice).ToList();
            var itemPriceDateLow= itemPriceDate.OrderBy(c => c.qtPrice).ThenBy(d => d.Invoice.DateInvoice);
            ViewBag.ItemPrice = itemPriceDateLow; ```

【问题讨论】:

  • 不管你怎么做,你都需要一个聚合值(min),这基本上意味着遍历列表两次。既然是这种情况,我建议您不要尝试使用 1-liner,而是将其拆分。

标签: c# asp.net-mvc list listview model-view-controller


【解决方案1】:

首先从 List(itemPrice) 中找出最小值。

double lowest_price = itemPrice.Min(c => c.qtPrice);

接下来,从列表中删除最低的元素。

var itemToRemove = itemPrice.Single(c => c.qtPrice == lowest_price);
itemPrice.Remove(itemToRemove);

接下来,根据输入的日期对剩余的列表进行排序。

var newList = itemPrice.OrderByDescending(d => d.Invoice.DateInvoice).ToList();

最后,在第一个索引处添加最低元素

newList.Insert(0, lowest_price);

【讨论】:

  • 所以这是 99% 的好。在我的示例中,我需要这样做。十进制最低价格 = (十进制)itemPrice.Min(c => c.qtPrice); var itemToRemove = itemPrice.Single(c => c.qtPrice == minimum_price); itemPrice.Remove(itemToRemove); var newList = itemPrice.OrderByDescending(d => d.Invoice.DateInvoice).ToList(); newList.Insert(0, itemToRemove);
  • 所以有一个问题:“var itemToRemove = itemPrice.Single(c => c.qtPrice ==lowest_price);”如果有两个或多个相同的 qtPrice == minimum_price 它会引发错误。
  • 如果有多个相同的值,您可以尝试 RemoveAll 从 List 中删除所有匹配的元素。 itemPrice.RemoveAll(c => c.qtPrice == minimum_price)
  • 谢谢你的评论,但这不是我要走的路。它有效,但前提是价格是独一无二的。
【解决方案2】:

LINQ 在工作时很棒,但有时会做一些意想不到的事情。根据您的数据集有多大,您最好将其作为一个返回已排序数据的存储过程。

如果数据集很小,或者您不得不使用 C# 来执行此操作,则可以选择使用自定义排序功能。在不知道数据的确切结构的情况下,这更多是作为一个需要进行相应调整的笼统示例。

假设您的列表存储在 itemPrice 变量中,如果您执行以下操作:

itemPrice.Sort((a, b) => {
                  int retVal = a.qtPrice < b.qtPrice;
                  return ret != 0 ? ret : a.Invoice.DateInvoice < b.Invoice.DateInvoice;
              });

将按 qtPrice 排序,然后回退到 DateInvoice 字段;您可能需要将小于换成大于以获得所需的订单。

【讨论】:

    【解决方案3】:

    一种就足够了。我认为应该是:

    var itemPriceDateLow= itemPriceDate.OrderBy(c => c.qtPrice).ThenBy(d => d.Invoice.DateInvoice);
    

    这显然会给你整个收藏。如果你想获得最顶层的元素,你可能想使用 .First()。

    要记住的一件事 - ThenBy、OrderBy 默认是升序的。

    看看这个例子:

    class Program
    {
    
        static void Main(string[] args)
        {
            List<ItemPrice> items = new List<ItemPrice>();
            items.Add(new ItemPrice() { Date = DateTime.Now, QtyPrice = 1});
            items.Add(new ItemPrice() { Date = DateTime.Now.AddDays(-1), QtyPrice = 1});
            items.Add(new ItemPrice() { Date = DateTime.Now, QtyPrice = 2});
    
            var sortedItem = items.OrderBy(p => p.QtyPrice).ThenBy(p => p.Date).First();
            Console.WriteLine($"Default Ascending sort {sortedItem.Date}, {sortedItem.QtyPrice}");
    
            var sortedItemWithReverseDate = items.OrderBy(p => p.QtyPrice).ThenByDescending(p => p.Date).First();
            Console.WriteLine($"Descending sort on date {sortedItemWithReverseDate.Date}, {sortedItemWithReverseDate.QtyPrice}");
        }
    }
    
    class ItemPrice {
        public DateTime Date { get; set; }
        public decimal QtyPrice { get; set; }
    }
    

    它会给你:

    默认升序排序 16/08/2021 12:47:34, 1 降序排序日期 17/08/2021 12:47:34, 1

    【讨论】:

      【解决方案4】:

      在这种情况下,您需要对集合进行两次迭代,因为您首先需要知道聚合值(最小值)。然后,您可以使用自定义比较器,如下所示。

      public class CustomComparer : IComparer<Item> 
      {
          private int _minValue;
          public CustomComparer(int minValue)
          {
              _minValue= minValue;
          }
      
          public int Compare(Item instanceA, Item instanceB)
          {
              if(instanceA.Price == _minValue) return -1;
              if(instanceB.Price == _minValue) return 1;
              return instanceA.InputDate.CompareTo(instanceB.InputDate);
          }
      }
      

      现在您可以获取结果为

      var min = list.Min(x=>x.Price);
      var result = list.OrderBy(x=>x,new CustomComparer(min));
      

      例子,

      public class Item
      {
          public int Price{get;set;}
          public DateTime InputDate{get;set;}
      }
      var list = new List<Item>
      {
              
              new Item{Price = 2,  InputDate=new DateTime(2021,3,1)},
              new Item{Price = 12, InputDate=new DateTime(2021,7,1)},
              new Item{Price = 12, InputDate=new DateTime(2021,9,1)},
              new Item{Price = 42, InputDate=new DateTime(2021,1,1)},
              new Item{Price = 32, InputDate=new DateTime(2021,6,1)},
              new Item{Price = 22, InputDate=new DateTime(2021,4,1)},
              new Item{Price = 2,  InputDate=new DateTime(2021,3,2)},
              new Item{Price = 12, InputDate=new DateTime(2021,2,1)}
      };
          
      var min = list.Min(x=>x.Price);
      var result = list.OrderBy(x=>x,new CustomComparer(min));
      
      

      输出

      【讨论】:

        【解决方案5】:

        感谢您的所有输入。

        对我来说正确的方法是。

        按“OrderByDescending(by date)”排序我的“itemPrice”列表

        然后从 List(itemPrice) 中找出最小值。

        double lowest_price = itemPrice.Min(c =&gt; c.qtPrice);

        然后声明一个新的List

        List&lt;qtInvoice&gt; newItemPrice = new List&lt;qtInvoice&gt;();

        将所有“lowest_price”添加到“newItemPrice”列表的第一个循环

        foreach (var item in itemPriceDate)
                    {
                        if (item.qtPrice == lowest_price)
                        {
                            newItemPrice.Add(item);
                        }
                    }
        

        然后在第二个循环中,将所有其余价格添加到“newItemPrice”列表中

        foreach (var item in itemPriceDate)
                    {
                        if (item.qtPrice != lowest_price)
                        {
                            newItemPrice.Add(item);
                        }
                    }
        

        【讨论】:

          猜你喜欢
          • 2020-10-01
          • 2014-01-18
          • 1970-01-01
          • 1970-01-01
          • 2013-06-29
          • 2010-10-23
          • 2017-06-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多