Reputation: 13
I have a list that looks like this:
Apple - 67 $ - 345 PIECES - 19:03
Banana - 45 $ - 341 PIECES - 12:02
Monkey - 34 $ - 634 PIECES - 16:01
And I want to order that list by the result of (money * amount) ordered, sort of "highest order ranking"
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();
}
However my code keeps crashing stating that the format is incorrect
Any clue anyone?
Upvotes: 1
Views: 66
Reputation: 415735
First do this:
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 - (\d{1,2}:\d{2})");
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;
}
}
Then use the type like so:
var result = finalResultOfTradeFiltering.
Select(t => Trade.Parse(t)).
OrderByDescending(t => t.Price * t.Quantity).
Select(t => t.OriginalLine);
Note the lack of a ToList()
call. Sticking with IEnumerable as much as possible, rather than converting to a List again after each step, will save on RAM and sometimes CPU, making the code much faster and more efficient. Don't convert to a List until you really need to, which is likely much later than you would think.
Even better if you are able to convert the strings to objects much earlier in your process, and not return them back to strings until after all the other processing is finished.
Upvotes: 1
Reputation: 163287
You might use a pattern to get capture the digits and then do the calculation using Sort.
(\d+) \$ - (\d+) PIECES
(\d+) \$
Capture group 1 for the money, match 1+ digits, a space and $
-
Match literally(\d+) PIECES
Capture group 2 for the amount, match 1+ digits and PIECES
Assuming the pattern matches for all the given strings:
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));
Output
Apple - 67 $ - 345 PIECES - 19:03
Monkey - 34 $ - 634 PIECES - 16:01
Banana - 45 $ - 341 PIECES - 12:02
Upvotes: 0