How to design an algorithm that iterates through many lists in an unknown order at compile time?

75 Views Asked by At

I'm creating a program which processes data according to user-defined settings. During the processing, I have a few related lists that must be iterated through according to these user-defined settings; the user decides the order in which these lists are iterated through.

I'm wondering how I can design an algorithm for iterating though these lists while still having very maintainable code. The idea here is not to end up with a function that has an enormous switch-case where each case does iteration of one of the lists.

Example:
Suppose the data I need to process is a list of different types of food. The user must specify the order in which different food groups are processed. The food groups are simply lists that store miscellaneous food items:

List<string> grains = new List<string> { "Bread", "Pasta", "Cereal", "Rice" };
List<string> vegetables = new List<string> { "Corn", "Pea", "Carrot", "Tomato" };
List<string> fruits = new List<string> { "Apple", "Orange", "Banana", "Pear" };
List<string> meat = new List<string> { "Beef", "Chicken", "Pork", "Turkey" };
List<string> diary = new List<string> { "Milk", "Cheese", "Yogurt", "Cream" };

The user's desired order is stored in another list. Below describes one possible order:

List<string> order = new List<string> 
{ 
    "grains",      //Grains processed first.
    "vegetables", 
    "fruits", 
    "meat", 
    "diary"        //Dairy processed last.
};

For the sake of explaining how it works I will use the undesired switch-case:

foreach(string foodGroup in order)
{
    switch(foodGroup)
    {
        case "grains":
            foreach(string foodItem in grains)
            {
                ProcessFood(foodItem);
            }
            break;
        case "vegetables":
            foreach(string foodItem in vegetables)
            {
                ProcessFood(foodItem);
            }
            break;
        case "fruits":
            foreach(string foodItem in fruits)
            {
                ProcessFood(foodItem);
            }
            break;
        case "meat":
            foreach(string foodItem in meat)
            {
                ProcessFood(foodItem);
            }
            break;
        case "diary":
            foreach(string foodItem in diary)
            {
                ProcessFood(foodItem);
            }
            break;
    }
}

In my application the case statements would actually contain a lot more code than the simple foreach-loops in the example. Is there a better way to design this algorithm? Although unnecessary, I am wondering if there is also a scalable way to design an algorithm like this (adding/removing a new food group doesn't break the algorithm).

1

There are 1 best solutions below

0
On BEST ANSWER

Make it a dictionary:

Dictionary<string, List<string>> lists = new Dictionary<string, List<string>>();
lists["grains"] = new List<string> { "Bread", "Pasta", "Cereal", "Rice" };
lists["vegetables"] = new List<string> { "Corn", "Pea", "Carrot", "Tomato" };
lists["fruits"] = new List<string> { "Apple", "Orange", "Banana", "Pear" };
lists["meat"] = new List<string> { "Beef", "Chicken", "Pork", "Turkey" };
lists["diary"] = new List<string> { "Milk", "Cheese", "Yogurt", "Cream" };

Now you can do:

foreach(string foodGroup in order)
{
   foreach(string foodItem in lists[foodGroup])
   {
      ProcessFood(foodItem);
   }
}

Actually there is also some nicer syntax in C# for the initialization. See: http://msdn.microsoft.com/en-us/library/bb531208.aspx