【问题标题】:Sort list by price c#按价格排序列表c#
【发布时间】:2021-02-12 03:38:36
【问题描述】:

我正在尝试根据列表中每个项目的价格对列表进行排序。

这是我希望输出的样子:

            ROLLS_ROYCE1 -- 6.608 €
            ROLLS_ROYCE3 -- 4.956 €
            ROLLS_ROYCE2 -- 0.826 €

但是,这是当前输出的实际情况:

            ROLLS_ROYCE1 -- 6.608 €
            ROLLS_ROYCE2 -- 0.82 €
            ROLLS_ROYCE3 -- 4.956 €

这是我的代码:

public void MyFunction() 
{
   List<string> mylist = new List<string>(new string[]
   {
      "ROLLS_ROYCE1 -- 0,826 € -- 8 PCS -- 14:02:53.876",
      "ROLLS_ROYCE2 -- 0,826 € -- 1 PCS -- 17:02:53.888",
      "ROLLS_ROYCE3 -- 0,826 € -- 6 PCS -- 18:09:55.888"
   });

   foreach (string f in mylist)
   {
      decimal b = Convert.ToDecimal(GetPrice(f), CultureInfo.GetCultureInfo("de-DE")) * Convert.ToDecimal(GetPieces(f));
      tradesforbigbuyslist += GetName(f) + " -- " + b.ToString() + " €" + 
         Environment.NewLine;
   }

   string[] splittedt2 = tradesforbigbuyslist.Split(new string[] { 
   System.Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            
   listBox3.DataSource = splittedt2;
}

public string GetPrice (string sourceline)
{
   string newstring = sourceline;
   string test1 = newstring.Replace(FetchThemAll.SubstringExtensions.Before(newstring, "--"), "");
   string textIWant = test1.Replace("--", "");
   string finalPrice = FetchThemAll.SubstringExtensions.Before(textIWant, "€");


   return finalPrice;
}

public string GetPieces(string sourceline)
{
   string ertzu = sourceline;
   string ertzu1 = FetchThemAll.SubstringExtensions.Between(ertzu, "€", "PCS");
   string ertzu2 = ertzu1.Replace("--", "");

   return ertzu2;
}

public string GetName(string sourceline)
{
   string barno = FetchThemAll.SubstringExtensions.Before(sourceline, "--");

   return barno;
}

如何正确排序这些字符串?

【问题讨论】:

  • 我稍微清理了代码的格式。看起来您缺少代码的开头(listBox3.DataSource = splittedt2; 之后的行上有一个不匹配的右括号 },暗示它是方法的结尾,但方法的开头不在您原来的题)。所以,我把它放在一个名为 MyFunction 的函数中 - 但请随时将其更改为您的实际方法名称。
  • 谢谢很多朋友@Donut
  • 为什么不尝试创建一个将这些值存储为属性并将每一行表示为对象的类。然后一个简单的 linq 查询就可以做到这一点并生成输出。
  • 为了帮助您修复代码,我们可能需要查看SubstringExtensions——即minimal reproducible example。但是,您不能只使用" -- " 子字符串使用string.Split(String, StringSplitOptions) 拆分"ROLLS_ROYCE1 -- 0,826 € -- 8 PCS -- 14:02:53.876" 字符串吗?请参阅:Split a string by another string in C#。您还可以使用相同的方法拆分 0,826 €8 PCS 子字符串。
  • 我通过 OrderByDescending 进行了尝试,但没有奏效 -- 那你能不能 edit 分享你的代码 minimal reproducible example -- 特别是没有成功的代码工作吗?

标签: c# arrays regex list sorting


【解决方案1】:

您可以通过将输入的每一行表示为具有此类相关属性的类来简化很多工作。如果准确性非常重要,就像处理真钱一样,那么固定精度数据类型应该代表价格。不过,为了简单起见,我在下面使用 double。

public class Car {
    public string Name;
    public short Pieces;
    public double Price;
}

然后您将在开始时解析它们并获得这些 Car 项目的列表。假设上面的价格代表您希望按您查找的列表排序的所需值,将通过以下 linq 查询获得。

var cars = new List<Cars>(); //Assumed definition
var frenchCulture = CultureInfo.CreateSpecificCulture("fr-FR"); //For Euros symbol usage later
//Parse Logic in Between
var sortedCars = cars.OrderByDescending(c => c.Price); //Linq Query yielding IEnumerable. If you must have a list simply append toList()

那么你的输出可能是这样设置的。

foreach (var car in sortedCars)
    // output with string.format("{0} -- {1}", car.Name, car.Price.ToString("C3", frenchCulture))

警告此代码未经测试,但应该大致正确。我确实对字符串格式做了一些研究。

【讨论】:

    【解决方案2】:

    嗯,mylist 中的字符串格式看起来足够一致,这样的东西可能会起作用(根本不使用扩展方法或正则表达式):

    var parsed = mylist.Select(line => line.Split(new[] { " -- " }, StringSplitOptions.None)).Select(parts => new
    {
       Name = parts[0],
       Price = Convert.ToDecimal(parts[1].Substring(0, parts[1].IndexOf(' '))),
       Pieces = Convert.ToInt32(parts[2].Substring(0, parts[2].IndexOf(' ')))
    });
    
    var sorted = parsed.OrderByDescending(x => x.Price * x.Pieces);
    

    然后你可以用sorted 做任何你想做的事情 - 例如。将项目转换回字符串并在listBox3 中显示。

    【讨论】:

    • 非常感谢您的回答,不幸的是我无法编译,出现以下错误 ` var parsed = mylist.Select(line => line.Split(" -- ")).Select(parts => new Cannot convert string into char @甜甜圈
    • @HassanBelHaq 试试line.Split(new [] { " -- " }, StringSplitOptions.None)
    【解决方案3】:

    这就是我所做的:我已经对此进行了测试,它似乎有效。

        public void MyFunction() 
    {
       List<string> mylist = new List<string>(new string[]
       {
          "ROLLS_ROYCE1 -- 0,826 € -- 8 PCS -- 14:02:53.876",
          "ROLLS_ROYCE2 -- 0,826 € -- 1 PCS -- 17:02:53.888",
          "ROLLS_ROYCE3 -- 0,826 € -- 6 PCS -- 18:09:55.888"
       });
       
       var map = new Dictionary<string, double>();
       foreach (string f in mylist)
       {
          var inputs = f.Split(" -- "); //Creates a list of strings
    
          var unitPrice = Convert.ToDouble(inputs[1].Split(' ')[0]);
          var numUnits = Convert.ToDouble(inputs[2].Split(' ')[0]);
           
          var key = inputs[0];
          if(map.ContainsKey(key)) map[key] = numUnits*unitPrice;
          else map.Add(key, numUnits*unitPrice);      
       }
    
       var sortedMap = map.OrderByDescending(x=>x.Value);
    
       foreach(var item in sortedMap){
         Console.WriteLine($"{item.Key} -- {item.Value} €");
       }
    }
    

    【讨论】:

      【解决方案4】:

      这对你来说可能有点矫枉过正,但在这种情况下,我通常会创建一个知道如何将其中一行解析为强类型属性的类,例如 NamePriceQuantity、等等。通常我会创建一个名为Pricestatic 方法,它接受input 字符串并返回该类的一个实例。

      在这种情况下,它看起来像:

      public class Item
      {
          public string Name { get; set; }
          public decimal Price { get; set; }
          public int Quantity { get; set; }
          public TimeSpan Time { get; set; }
          public decimal Total => Price * Quantity;
      
          public static Item Parse(string input)
          {
              if (input==null) throw new ArgumentNullException();
      
              var parts = input
                  .Split(new[] {"--", " ", "€", "PCS"}, 
                      StringSplitOptions.RemoveEmptyEntries);
      
              if (parts.Length != 4)
                  throw new ArgumentException(
                      "Input must contain 4 sections separated by \"--\"");
      
              decimal price;
              if (!decimal.TryParse(parts[1], out price))
                  throw new ArgumentException(
                      "Price must be a valid decimal in the second position");
      
              int quantity;
              if (!int.TryParse(parts[2], out quantity))
                  throw new ArgumentException(
                      "Quantity must be a valid integer in the third position");
      
              TimeSpan time;
              if (!TimeSpan.TryParse(parts[3], out time))
                  throw new ArgumentException(
                      "Time must be a valid TimeSpan in the fourth position");
      
              return new Item
              {
                  Name = parts[0],
                  Price = price,
                  Quantity = quantity,
                  Time = time
              };
          }
      }
      

      随着课堂上的工作,我们的主要代码被大大简化了:

      List<string> mylist = new List<string>(new string[]
      {
          "ROLLS_ROYCE1 -- 0,826 € -- 8 PCS -- 14:02:53.876",
          "ROLLS_ROYCE2 -- 0,826 € -- 1 PCS -- 17:02:53.888",
          "ROLLS_ROYCE3 -- 0,826 € -- 6 PCS -- 18:09:55.888"
      });
      
      List<Item> orderedItems = mylist
          .Select(Item.Parse)
          .OrderByDescending(item => item.Total)
          .ToList();
      

      然后显示项目就像这样简单:

      orderedItems.ForEach(item => Console.WriteLine($"{item.Name} -- {item.Total} €"));
      

      输出

      【讨论】:

      • 只有计算出来的价格对我来说没有正确格式(使用 net 4.5)才能正常工作,我是否必须使用 CultureInfo 或类似的东西? @RufusL
      • 它们在哪些方面没有正确制定?我不得不将原始字符串中的逗号更改为句点,因为句点是美国的小数分隔符。您在自己的文化中看到了什么?
      • 我只看到数字,例如 6608 或 4956,我来自德国
      • 这些数字是否正确,您只想添加千位分隔符?或者他们根本就不是正确的数字?您可以尝试将它们格式化为货币:$"{kvp.Key}={kvp.Value:C}"
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-08
      相关资源
      最近更新 更多