HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Validate the order of a List<string> by custom strings

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
validatetheordercustomliststringsstring

Problem

I have a test where I have to validate the order of items in a List based on a pre-defined hierarchy that is being given to me as part of my assignment. Here it is below.

  • Cat



  • Dog



  • Horse



  • Elephant



The items in the list would only ever be those four types, but the size of list is not limited. The list will be passed in as part of the method. There can be multiple of each or none at all. The below two list would be valid:

  • Cat



  • Cat



  • Dog



  • Elephant



This would not.

  • Elephant



  • Dog



  • Horse



  • Cat



Below is what I have so far, and I feel as though there is a much more elegant solution. In particular, I would like to minimize the amount of bools and if statements I am using.

public bool ValidateAnimalOrder(List listOfAnimals)
{
    bool catExists = false;
    bool dogExists = false;
    bool horseExists = false;
    bool elephantExists = false;

    for (int x = 0; x < listOfAnimals.Count; x++)
    {
        if (listOfAnimals[x] == "Cat")
        {
            catExists = true;
            if(dogExists || horseExists || elephantExists)
            {
                return false;
            }
        }
        if (listOfAnimals[x] == "Dog")
        {
            dogExists = true;
            if (horseExists || elephantExists)
            {
                return false;
            }
        }
        if (listOfAnimals[x] == "Horse")
        {
            horseExists = true;
            if (elephantExists)
            {
                return false;
            }
        }
        if (listOfAnimals[x] == "Elephant")
        {
            elephantExists = true;
        }

    }

    return true;
}

Solution

Dictionary

I'd prefer to store animal names and their "values" in a dictionary.

private static readonly Dictionary AnimalValues = new Dictionary
        {
            { "Cat", 1 },
            { "Dog", 2 },
            { "Horse", 3 },
            { "Elephant", 4 }
        };


Then the validation method will look like:

public static bool IsValidAnimalOrder(IEnumerable animalNames)
{
    int prevValue = 0;
    foreach (string animalName in animalNames)
    {
        int curValue;
        if (!AnimalValues.TryGetValue(animalName, out curValue))
        {
            // If the animal's name is absent in the dictionary.
            return false;
        }
        if (curValue < prevValue)
        {
            // If the current animal's value less than the previous one.
            return false;
        }
        prevValue = curValue;
    }
    return true;
}


switch

Alternative way is to use the switch operator instead of a dictionary as follows:

public static bool IsValidAnimalOrder(IEnumerable animalNames)
{
    int prevValue = 0;
    foreach (string animalName in animalNames)
    {
        int curValue;
        switch (animalName)
        {
            case "Cat":
                curValue = 1;
                break;
            case "Dog":
                curValue = 2;
                break;
            case "Horse":
                curValue = 3;
                break;
            case "Elephant":
                curValue = 4;
                break;
            default:
                // If the animal's name is not listed above.
                return false;
        }
        if (curValue < prevValue)
        {
            // If the current animal's value less than the previous.
            return false;
        }
        prevValue = curValue;
    }
    return true;
}


IEnumerable problem

As @Mat's Mug♦ mentioned, IEnumerable doesn't guarantee the order of its elements. So you could change argument type to IList or IReadOnlyList. But this will reject another enumerations with the specified order: IOrderedEnumerable and IOrderedQueryable.

As a workaround you could make the method above private and declare public overloads accepting all the suitable enumeration types above as argument:

public static bool IsValidAnimalOrder(IReadOnlyList animalNames)
{
    return IsValidAnimalOrder((IEnumerable)animalNames);
}

public static bool IsValidAnimalOrder(IOrderedEnumerable animalNames)
{
    return IsValidAnimalOrder((IEnumerable)animalNames);
}

public static bool IsValidAnimalOrder(IOrderedQueryable animalNames)
{
    return IsValidAnimalOrder((IEnumerable)animalNames);
}

Code Snippets

private static readonly Dictionary<string, int> AnimalValues = new Dictionary<string, int>
        {
            { "Cat", 1 },
            { "Dog", 2 },
            { "Horse", 3 },
            { "Elephant", 4 }
        };
public static bool IsValidAnimalOrder(IEnumerable<string> animalNames)
{
    int prevValue = 0;
    foreach (string animalName in animalNames)
    {
        int curValue;
        if (!AnimalValues.TryGetValue(animalName, out curValue))
        {
            // If the animal's name is absent in the dictionary.
            return false;
        }
        if (curValue < prevValue)
        {
            // If the current animal's value less than the previous one.
            return false;
        }
        prevValue = curValue;
    }
    return true;
}
public static bool IsValidAnimalOrder(IEnumerable<string> animalNames)
{
    int prevValue = 0;
    foreach (string animalName in animalNames)
    {
        int curValue;
        switch (animalName)
        {
            case "Cat":
                curValue = 1;
                break;
            case "Dog":
                curValue = 2;
                break;
            case "Horse":
                curValue = 3;
                break;
            case "Elephant":
                curValue = 4;
                break;
            default:
                // If the animal's name is not listed above.
                return false;
        }
        if (curValue < prevValue)
        {
            // If the current animal's value less than the previous.
            return false;
        }
        prevValue = curValue;
    }
    return true;
}
public static bool IsValidAnimalOrder(IReadOnlyList<string> animalNames)
{
    return IsValidAnimalOrder((IEnumerable<string>)animalNames);
}

public static bool IsValidAnimalOrder(IOrderedEnumerable<string> animalNames)
{
    return IsValidAnimalOrder((IEnumerable<string>)animalNames);
}

public static bool IsValidAnimalOrder(IOrderedQueryable<string> animalNames)
{
    return IsValidAnimalOrder((IEnumerable<string>)animalNames);
}

Context

StackExchange Code Review Q#142533, answer score: 13

Revisions (0)

No revisions yet.