28

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.)

9 Answers 9

51

Using linq:

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

W/o linq:

Array.IndexOf(listString.Split(','), "apple") >= 0
6
  • 1
    I don't get it. String.Split returns an array. Arrays don't have a Contains method. Commented Apr 6, 2010 at 16:52
  • 2
    you must be using .NET3.5+, and have 'using System.Linq' somewhere.
    – nothrow
    Commented Apr 6, 2010 at 16:53
  • 1
    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. Commented Apr 6, 2010 at 16:54
  • 2
    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. Commented Apr 6, 2010 at 16:58
  • 4
    If you don't have access to linq, you can still use: Array.IndexOf(listString.Split(','), "apple") >= 0 Commented Apr 6, 2010 at 21:58
13
(","+listString+",").Contains(","+testWord+",");

but not straight-forward, too.

3
  • 1
    I used to use this method all the time. It has the virtue of not creating N new strings.
    – harpo
    Commented Apr 6, 2010 at 16:52
  • 3
    If your comma-separated string is long this is more space-efficient than split. Commented Apr 6, 2010 at 16:53
  • 1
    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. Commented Apr 6, 2010 at 17:03
8

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) + "(?=,|$)")
3
  • 4
    Of course, if testWord contains any symbols that have meaning in a regular expression then you've got a big problem here. Commented Apr 6, 2010 at 17:26
  • 1
    Whoah, I didn't think about that. Good point! I suppose I'm vulnerable to a regex-injection attack! :) Commented Apr 6, 2010 at 17:37
  • What do you mean? Regexes rock! Commented Apr 18, 2010 at 17:06
3

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

2
  • Thanks for including the non-Linq version. Too bad it's so verbose. Commented Apr 6, 2010 at 17:14
  • 3
    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
    Commented Apr 6, 2010 at 17:44
2

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);
1
  • 1
    Oh, that makes my complicated look-ahead solution look really silly. Thanks. Commented Apr 19, 2010 at 2:11
1

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);
2
  • If you're using linq then IEnumerable<T>.Compare has an overload which takes an IEqualityComparer<T>.
    – Lee
    Commented Apr 6, 2010 at 17:44
  • +1 for culturally-sensative string comparisons! "Caf\u00E9" and "Cafe\u0301" look identical, they should compare as equal! Commented Apr 7, 2010 at 15:26
1

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.

0

This is solution for ignoring case and culture(or select one of the property of StringComparer)

var commaDelimitedString = "string1,string2,string3,string4";
var testString = string2.trim; // trim to remove the spaces coz you may be getting it from UI
if(commaDelimitedString.split(',').contains(testString,StringComparer.InvariantCultureIgnoreCase))
{
     //TODO: What to do when condition is true
}
else
{
     //TODO: What to do when condition is false
}
0
                 public bool GetIsExistSubstring(string mainstring, string substring)
    {        
        bool Isexist=false;
        int i = -1;
        mainstring = string.Format(",{0},", mainstring);//so it will be like  ,1,2,3,
        substring = string.Format(",{0},", substring);//so it will be like  ,1,
        i=mainstring.IndexOf(substring);

        if(i!=-1)
        {
            Isexist = true;
        }
        return Isexist;
    }
1
  • Please try to answer new questions. This was asked in 2010 and also was answered. Commented Aug 18, 2016 at 7:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.