tags:

views:

61

answers:

5

I'm doing some validation where I need to check for certain combinations between two values. For example, if string1 is "fruit", valid values for string2 are "apple", "banana" and "pear". Currently, I'm doing this:

switch(string1)
{
  case "fruit":
    if(string2 != "apple" && string2 != "banana")
    {
      return false;
    }
    break;
  case "meat":
    if(string2 != "beef" && string2 != "pork")
    {
      return false;
    }
  default:
    return true;
    break;
}

This is really two questions. The first is, is there any good way to do something more like this:

switch(string1)
{
  case "fruit":
    if(string2 NOT IN ("apple", "banana"))
    {
      return true;
    }
    break;
  case "meat":
    if(string2 NOT IN ("beef", "pork"))
    {
      return false;
    }
  default:
    return true;
    break;
}

The second part of this question is likely what will get answered first: is there a better/best way to do this? I'm not the most amazing coder in the world and this is the first "off the top of my head" solution, so I'm certainly open to better ones. Thanks!

A: 

You can shorten your cases down to:

switch(string1)
{
  case "fruit":
    return  new[] { "apple", "banana" }.Contains(string2);
  case "meat":
    return  new[] { "beef", "pork" }.Contains(string2);
  default:
    return true;
    break;
}

I think style is, to a large degree, dependent upon personal taste. This is my taste...I think it's easy to add a new value in there with the array style, with as little overhead (I believe, someone feel free to correct me) that you can get with an array/collection style of "if-in" type check.

Nick Craver
Not too fond of this, since it will recreate the array each time through.
Joel
@Joel - Yes, but I don't know of a shorter way...if it's a small list (all I use it for), the array creation is still more performant than `List<T>` searching. It's no more expensive than using something with `params string[] args` in it...same thing happens. If the use case is a loop, I agree...create it outside of course.
Nick Craver
I agree with @Joel - I like the looks of this Nick, but in my case I'm going to be doing this potentially quite a few times in a row, so I'd rather not recreate the array each time.
Zannjaminderson
You just need to give it a name at the class level. Viola!
Joel
+2  A: 

Yeah, there's a better way. You want to create a map, which associates your "category" ("fruit") with a string List of your elements ("apple", "banana", etc.). Then you want to look up your "string1" in your example above from the map and see if your associated string List Contains() your "string2".

This makes it entirely data-driven, and leverages the built-in abilities of the Collections more successfully.

McWafflestix
+1  A: 

A variation on Nick's answer. Create two lists and use the contains method against them.

public List<string> Fruit = new List<string>{"apple", "banana"};
public List<string> Meat = new List<string>{"beef", "pork"};

switch (string1)
{
    case "fruit":
        return Fruit.Contains(string2);
    case "meat":
        return Meat.Contains(string2);
}
Beaner
A: 

You could do something like this:

Dictionary<string, string> map  = new Dictionary<string, string>();

map.add("banana", "fruit");
map.add("apple", "fruit");
map.add("pear", "fruit");

map.add("beef", "meat");
map.add("pork", "meat");


if(map[string2] == string1)
    return true;
scottm
+1  A: 

Here is a way using Linq:

Dictionary<string, IList<string>> validValues = new Dictionary<string, IList<string>>() 
{ 
    { "fruit", new List<string>() { "apple", "banana" } }, 
    { "meat", new List<string>() { "pork", "beef" } } 
};

if (validValues.FirstOrDefault(x => x.Key == string1 && x.Value.Contains(string2)).Value != null)
{
    return true;
}

return false;
David Hall