Master Chef
Master Chef

Reputation: 65

C# - Sorting listbox alphabetically

I need helping sorting a textfile alphabetically which has been read into a listbox. Is there any way of possibly having the list box sort this set of data which is contain in a textfile:

pizza, margherita, regular, 4.40, dough, 1.00, sauce, 0.25, mozzarella, 0.75
pizza, margherita, large, 5.40, dough, 1.44, sauce, 0.36, mozzarella, 1.08
pizza, margherita, extra-large, 7.50, dough, 1.79, sauce, 0.45, mozzarella, 1.34
pizza, pepperoni, regular, 5.00, dough, 1.00, sauce, 0.25, mozzarella, 0.75, pepperoni, 2.0
pizza, pepperoni, large, 6.00, dough, 1.44, sauce, 0.36, mozzarella, 1.08, pepperoni, 2.88
pizza, pepperoni, extra-large, 10.00, dough, 1.79, sauce, 0.45, mozzarella, 1.342, pepperoni, 3.58
pizza, hawaiian, regular, 5.50, dough, 1.00, sauce, 0.25, mozzarella, 0.75, ham, 1.50, pineapple, 0.5
pizza, hawaiian, large, 6.50, dough, 1.44, sauce, 0.36, mozzarella, 1.08, ham, 2.16, pineapple, 0.72
pizza, hawaiian, extra-large, 11.00, dough, 1.79, sauce, 0.45, mozzarella, 1.34, ham, 2.69, pineapple, 0.90
pizza, vegetable, regular, 5.40, dough, 1.00, sauce, 0.25, mozzarella, 0.75, olives, 0.75, spinach, 0.25, mushrooms, 1.00
pizza, vegetable, large, 6.40, dough, 1.44, sauce, 0.36, mozzarella, 1.08, olives, 1.08, spinach, 0.36, mushrooms, 1.44
pizza, vegetable, extra-large, 10.00, dough, 1.79, sauce, 0.45, mozzarella, 1.342, olives, 1.34, spinach, 0.45, mushrooms, 1.79
pizza, meaty, regular, 5.50, dough, 1.00, sauce, 0.25, mozzarella, 0.75, chicken, 0.50, beef, 0.50, ham, 0.25, pepperoni, 0.25
pizza, meaty, large, 6.50, dough, 1.44, sauce, 0.36, mozzarella, 1.08, chicken, 0.72, beef, 0.72, ham, 0.36, pepperoni, 0.36
pizza, meaty, extra-large, 13.00, dough, 1.79, sauce, 0.45, mozzarella, 1.34, chicken, 1.08, beef, 1.08, ham, 0.45, pepperoni, 0.45
burger, beef, regular, 2.30, bun, 1, beef patty, 1
burger, beef, large, 3.40, bun, 1, beef patty, 2
burger, chicken, regular, 3.00, bun, 1, chicken fillet, 1
burger, chicken, large, 4.10, bun, 1, chicken fillet, 2
burger, vegetarian, regular, 2.50, bun, 1, falafel, 1
burger, vegetarian, large, 3.60, bun, 1, falafel, 2
sundry, chips, regular, 1.20, chips, 1
sundry, onion-rings, regular, 1.70, onion rings, 1
sundry, coleslaw, regular, 1.00, coleslaw, 

Upvotes: 0

Views: 2404

Answers (3)

Rufus L
Rufus L

Reputation: 37020

To build on Rob's answer, you could also create a static method on the FoodItem class that knows how to create a FoodItem from a comma-separated string. You could call this method when reading the file, to simplify generating a list of food items.

Also, overriding the ToString() property on these classes makes displaying the items much easier too.

Here's the FoodItem class with a few additions:

public class FoodItem
{
    public string FoodCategory { get; set; }
    public string FoodType { get; set; }
    public string Size { get; set; }
    public double Price { get; set; }
    public List<Ingredient> Ingredients { get; set; }

    public FoodItem()
    {
        Ingredients = new List<Ingredient>();
    }

    public static FoodItem CreateFromCommaString(string commaSeparatedValues)
    {
        var foodItem = new FoodItem();
        if (string.IsNullOrWhiteSpace(commaSeparatedValues)) return foodItem;

        var values = commaSeparatedValues.Split(',')
            .Select(value => value.Trim()).ToList();

        double price;
        foodItem.FoodCategory = values[0];
        if (values.Count > 1) foodItem.FoodType = values[1];
        if (values.Count > 2) foodItem.Size = values[2];
        if (values.Count > 3 && double.TryParse(values[3], out price))
        {
            foodItem.Price = price;
        }

        if (values.Count > 4)
        {
            for (int i = 4; i < values.Count; i += 2)
            {
                var ingredient = new Ingredient {Name = values[i]};
                double qty;
                if (values.Count > i + 1 && double.TryParse(values[i + 1], out qty))
                {
                    ingredient.Quantity = qty;
                }
                foodItem.Ingredients.Add(ingredient);
            }
        }

        return foodItem;
    }

    public override string ToString()
    {
        return string.Format("{0}: {1} ({2}) = ${3:0.00}. Contains: {4}",
            FoodCategory, FoodType, Size, Price, string.Join(", ", Ingredients));
    }
}

And the Ingredient class with a ToString override:

public class Ingredient
{
    public string Name { get; set; }
    public double Quantity { get; set; }
    public override string ToString()
    {
        return $"{Name}: {Quantity}";
    }
}

Then, populating a list of the classes is simple: just get all the file lines, and for each one generate a new FoodItem and add it to your list. And once that's done, you can order the list by multiple fields, using OrderBy and ThenBy:

private static void Main()
{
    var filePath = @"f:\public\temp\temp.txt";

    var foodItems = new List<FoodItem>();

    foreach (var fileLine in File.ReadAllLines(filePath))
    {
        foodItems.Add(FoodItem.CreateFromCommaString(fileLine));
    }

    var sortedItems = foodItems
        .OrderBy(item => item.FoodCategory)
        .ThenBy(item => item.FoodType)
        .ThenBy(item => item.Price)
        .ToList();

    sortedItems.ForEach(Console.WriteLine);

    Console.Write("\nDone!\nPress any key to exit...");
    Console.ReadKey();
}

Output (click to enlarge):

enter image description here

Upvotes: 2

Rob Branaghan
Rob Branaghan

Reputation: 74

Is there anyway you can change the way your values are stored?

For example. You have

Burger, Vegetarian, Large, 3.60, bun,1, falafel,2 all in one comma separated line.

How about

Burger, Vegetarian, Large, 3.60, bun:1|falafel:2 then you would know that you have Product, Type, Size, Price, Ingredients and Ingredients is '|' separated and also, ':' between name and qty.

Anyway, if it was set out like that you could read it into a List of objects or a dictionary, so each item in the listbox can have the Key as the value, then you can use the values else where in the code easily.

public class FoodItem
{
   public string FoodCategory {get;set;}
   public string FoodType {get;set;}
   public string Size {get;set;}
   public double Price {get;set;}
   public List<Ingredient> Ingredients {get;set;}
}

public class Ingredient
{
   public string Name {get;set;}
   public int Quantity {get;set;}
}

Then when you read your text field parse each line into an instance of food item.

Another questions answer reading text files line by line.

https://stackoverflow.com/a/7980605/7683170

Upvotes: 1

Sunil Mathari
Sunil Mathari

Reputation: 870

Enable Sorted Property to true

listBox1.Sorted = true;

Upvotes: 3

Related Questions