Reputation: 65
I'm trying to sort a list based on the price for each item in the list.
Here's what I want my output to look like:
ROLLS_ROYCE1 -- 6.608 €
ROLLS_ROYCE3 -- 4.956 €
ROLLS_ROYCE2 -- 0.826 €
However, here's what the current output actually is:
ROLLS_ROYCE1 -- 6.608 €
ROLLS_ROYCE2 -- 0.82 €
ROLLS_ROYCE3 -- 4.956 €
Here's my code:
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;
}
How can I sort these strings correctly?
Upvotes: 2
Views: 1305
Reputation: 964
You could simplify a lot of this work by representing each line of input as a class with relevant properties like this. If accuracy is super important like with dealing real money then fixed precision data type should represent the price. However I am using double below for simplicity.
public class Car {
public string Name;
public short Pieces;
public double Price;
}
Then you would parse them at the beginning and have a list of these Car items. Assuming the Price above represents the desired value you wish to sort by the list you seek would be obtained by the following linq query.
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()
Then your output might be set like this.
foreach (var car in sortedCars)
// output with string.format("{0} -- {1}", car.Name, car.Price.ToString("C3", frenchCulture))
Warning that this code was not tested but should be approximately correct. I did do some research for the string format.
Upvotes: 2
Reputation: 37020
It may be overkill for you, but what I usually do in cases like this is create a class that knows how to parse one of those lines into strongly typed properties, like Name
, Price
, Quantity
, etc. Usually I create a static
method named Price
that takes in an input
string and returns an instance of the class.
In this case it would look something like:
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
};
}
}
With the work being done in the class, our main code is simplified tremendously:
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();
And then displaying the items would be as simple as:
orderedItems.ForEach(item => Console.WriteLine($"{item.Name} -- {item.Total} €"));
Output
Upvotes: 0
Reputation: 111
Here is what I did: I have tested this and it seems to work.
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} €");
}
}
Upvotes: 0
Reputation: 112815
Well, the format of your strings in mylist
looks consistent enough that something like this might work (without using extension methods or Regex at all):
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);
Then you can do whatever you want with sorted
- e.g. convert the items back to strings and display them in listBox3
.
Upvotes: 0