按价格排序列表,由列表内项目的子字符串计算#
Posted
技术标签:
【中文标题】按价格排序列表,由列表内项目的子字符串计算#【英文标题】:Sort list by a price, calculated by substrings from item inside list c# 【发布时间】:2021-09-30 16:51:57 【问题描述】:我有一个如下所示的列表:
Apple - 67 $ - 345 PIECES - 19:03
Banana - 45 $ - 341 PIECES - 12:02
Monkey - 34 $ - 634 PIECES - 16:01
我想按(金额*金额)的排序结果排序该列表,类似于“最高订单排名”
finalResultOfTradeFiltering = finalResultOfTradeFiltering.OrderBy(x => Convert.ToDecimal(FindTextBetween(x,"-","$").Replace(" ", String.Empty)) * Convert.ToInt32(FindTextBetween(x, "-", "PIECES").Replace(" ", String.Empty))).ToList();
public string FindTextBetween(string text, string left, string right)
// TODO: Validate input arguments
int beginIndex = text.IndexOf(left); // find occurence of left delimiter
if (beginIndex == -1)
return string.Empty; // or throw exception?
beginIndex += left.Length;
int endIndex = text.IndexOf(right, beginIndex); // find occurence of right delimiter
if (endIndex == -1)
return string.Empty; // or throw exception?
return text.Substring(beginIndex, endIndex - beginIndex).Trim();
但是我的代码不断崩溃,说明格式不正确
有什么线索吗?
【问题讨论】:
它将基于FindTextBetween
代码,但我的猜测是FindTextBetween(x, "-", "PIECES")
从第一个-
中找到文本,因此您尝试格式化67$-345
而不是@ 987654328@。请附上FindTextBetween
代码,以便我们确认是否是问题所在。
你应该写一个类,可以使用类类型将字符串列表转换为列表。
我很确定我已经在 foreach 循环中测试了 FindTextBetween,它正确地输出了金额和件数,所以没有错
如果可能尝试使用Regex
,而不是查找索引并提取子字符串
是的,问题正如我所怀疑的那样。 FindTextBetween
从-
的第一次出现开始。因此,您要么需要更新它以传入它应该开始的索引,要么告诉它跳过第一次出现。或者更好的是编写一个方法来将整个字符串解析为一个带有值的类,然后在你的代码中使用它。
【参考方案1】:
首先这样做:
public class Trade
public string Product get;set;
public decimal Price get;set;
public int Quantity get;set;
public string Time get;set; //Make this a DateTime or new TimeOnly later
public string OriginalLine get;set;
public static Trade Parse(string input)
var result = new Trade();
result.OriginalLine = input;
//example line
//Apple - 67 $ - 345 PIECES - 19:03
var exp = new RegEx(@" - (\d+) [$] - (\d+) PIECES - (\d1,2:\d2)");
var groups = exp.Match(input).Groups;
result.Price = Convert.ToDecimal(groups[1].Value);
result.Quantity = Convert.ToInt32(groups[2].Value);
result.Time = groups[3].Value;
int EndMarker = input.IndexOf(" - ");
result.Product = input.SubString(0, EndMarker).Trim();
return result;
然后像这样使用类型:
var result = finalResultOfTradeFiltering.
Select(t => Trade.Parse(t)).
OrderByDescending(t => t.Price * t.Quantity).
Select(t => t.OriginalLine);
请注意缺少ToList()
呼叫。尽可能坚持使用 IEnumerable,而不是在每一步之后再次转换为 List,这将节省 RAM,有时还会节省 CPU,从而使代码更快、更高效。在您真正需要之前不要转换为列表,这可能比您想象的要晚得多。
如果您能够在处理过程中更早地将字符串转换为对象,并且在所有其他处理完成之前不将它们返回为字符串,那就更好了。
【讨论】:
感谢 Joel 也是一个很好的答案,还可以获得计算值(例如,Apple - 67 $ - 345 PIECES - 19:03 - 23.115 $)我可以做这样的事情吗... = > t.originalline + (t.Price * t.Quantity) ? 不,原行是一个字符串。 始终注意值的数据类型。您只需要t.Price * t.Quanity
部分。【参考方案2】:
您可以使用模式来获取数字,然后使用排序进行计算。
(\d+) \$ - (\d+) PIECES
(\d+) \$
为钱捕获组 1,匹配 1+ 位数字、空格和 $
-
字面匹配
(\d+) PIECES
捕获组2的金额,匹配1+数字和 PIECES
假设模式匹配所有给定的字符串:
List<string> finalResultOfTradeFiltering = new List<string>()
"Apple - 67 $ - 345 PIECES - 19:03",
"Banana - 45 $ - 341 PIECES - 12:02",
"Monkey - 34 $ - 634 PIECES - 16:01"
;
var regex = @"(\d+) \$ - (\d+) PIECES";
finalResultOfTradeFiltering.Sort((a, b) =>
var matchA = Regex.Match(a, regex);
var matchB = Regex.Match(b, regex);
var valueA = int.Parse(matchA.Groups[1].Value) * int.Parse(matchA.Groups[2].Value);
var valueB = int.Parse(matchB.Groups[1].Value) * int.Parse(matchB.Groups[2].Value);
return valueB.CompareTo(valueA);
);
finalResultOfTradeFiltering.ForEach(s => Console.WriteLine(s));
输出
Apple - 67 $ - 345 PIECES - 19:03
Monkey - 34 $ - 634 PIECES - 16:01
Banana - 45 $ - 341 PIECES - 12:02
【讨论】:
非常感谢,我该如何实际使用它来进一步输出 price * pieces 的值?像这样的东西:Apple - 67 $ - 345 PIECES - 19:03 - 23.115 $ ? @HassanBrate 您可以再次格式化列表中的项目,然后根据需要格式化数字。见ideone.com/FPd8j5以上是关于按价格排序列表,由列表内项目的子字符串计算#的主要内容,如果未能解决你的问题,请参考以下文章
根据子列表中的第二个元素按字母顺序对列表进行排序,但不区分大小写[重复]
LeetCode 884. 两句话中的不常见单词 / 1342. 将数字变成 0 的操作次数(计算二进制长度统计1的个数) / 1763. 最长的美好子字符串(分治)