patterncsharpModerate
Validate the order of a List<string> by custom strings
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.
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:
This would not.
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.
- 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.
Then the validation method will look like:
switch
Alternative way is to use the
IEnumerable problem
As @Mat's Mug♦ mentioned,
As a workaround you could make the method above private and declare public overloads accepting all the suitable enumeration types above as argument:
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.