tags:

views:

151

answers:

7

I'm reading a comma-delimited list of strings from a config file. I need to check whether another string is in that list. For example:

"apple,banana,cheese"

If I check for "apple" I should find it, but if I check for "app" I should not.

What's the most straight-forward and concise way to do this? It doesn't have to be fast.

(I'll add my solution as an answer, but I'm hoping someone has something better.)

+7  A: 

Regex probably doesn't count as "straight-forward", but this is what I've got:

Regex.IsMatch(listString, "(?<=,|^)" + testWord + "(?=,|$)")

Update: Per Eric's comment below, this should be:

Regex.IsMatch(listString, "(?<=,|^)" + Regex.Escape(testWord) + "(?=,|$)")
Jeremy Stein
Of course, if testWord contains any symbols that have meaning in a regular expression then you've got a big problem here.
Eric Lippert
Whoah, I didn't think about that. Good point! I suppose I'm vulnerable to a regex-injection attack! :)
Jeremy Stein
What do you mean? Regexes rock!
Damian Powell
+8  A: 
(","+listString+",").Contains(","+testWord+",");

but not straight-forward, too.

Yossarian
I used to use this method all the time. It has the virtue of not creating N new strings.
harpo
If your comma-separated string is long this is more space-efficient than split.
0xA3
For .NET 2.0, I think this may be the best solution. It's not too hard to see why the commas are added, and it's just one method call. I like it.
Jeremy Stein
+9  A: 

Using linq:

listString.Split(',').Contains("apple")

W/o linq:

Array.IndexOf(listString.Split(','), "apple") >= 0
Fábio Batista
I don't get it. String.Split returns an array. Arrays don't have a Contains method.
Jeremy Stein
you must be using .NET3.5+, and have 'using System.Linq' somewhere.
Yossarian
There is a `Contains` LINQ extension method that can be used for an array. Though this would not work if you are using .Net 1.1 or 2.0.
Eclipsed4utoo
Not only is this not-too-slow, it's also instantly obvious what's going on. You can't say that about the Regex solution.
Lucas Jones
Oh, I see. My project was targeted to .NET 2.0. I'll have to check what the target machine supports.
Jeremy Stein
If you don't have access to linq, you can still use: `Array.IndexOf(listString.Split(','), "apple") >= 0`
Fábio Batista
+2  A: 

Another way might be to try using

bool contains = new List<string>("apple,banana,cheese".Split(',')).Contains("apple");
//or
bool b = "apple,banana,cheese".Split(',').Contains("apple");

List< T>.Contains Method

String.Split Method

Enumerable.Contains Method

astander
Thanks for including the non-Linq version. Too bad it's so verbose.
Jeremy Stein
Since Array implements IList<T>, you don't need to create a second List<string>. The following variant will work for .NET 2.0: ((IList<string>)listString.Split(',')).Contains(...)
Joe
+1  A: 

Here's an option that ignores case.

var food = "apple,banana,cheese";

bool containsApp = food.Split(',')
                       .Where(s => string.Compare("app", s, true) == 0)
                       .Count() > 0;

bool containsApple = food.Split(',')
                         .Where(s => string.Compare("apple", s, true) == 0)
                         .Count() > 0;

Console.WriteLine("Contains \"app\"? {0}", containsApp);
Console.WriteLine("Contains \"apple\"? {0}", containsApple);
Austin Salonen
If you're using linq then `IEnumerable<T>.Compare` has an overload which takes an `IEqualityComparer<T>`.
Lee
+1 for culturally-sensative string comparisons! "Caf\u00E9" and "Cafe\u0301" look identical, they should compare as equal!
Jeffrey L Whitledge
+1  A: 

The answer depends on what the syntax rules for your comma-delimited list are.

If the rules require that the list be exactly as you posted (no spaces, no trailing comma) then the task can be broken down into it's component pieces:

Does the string begin with apple,? (String.StartsWith)
Does the string end with ,apple? (String.EndsWith)
Does the string contain ,apple,? (String.Contains)

If the rules are more difficult then the Regex approach becomes the only way without fully processing the list or writing a heap of rules.

If you are checking for many items against the same string you'll want to just transform the string into a list which you cache and then check against. The String.Split method will do this for you.

David
+1  A: 

This works, but regexes are pretty slow if they get complicated. That said, the word boundary anchor makes this sort of thing pretty easy.

var foods = "apple,banana,cheese";

var match = Regex.Match(foods, @"\bapple\b");

if (match.Success)
    Console.WriteLine(match.Value);
Damian Powell
Oh, that makes my complicated look-ahead solution look really silly. Thanks.
Jeremy Stein