6

I have an array of strings

string[] tmp = foo();

If NONE of the strings in foo contain either "bar" or "baz" I want to execute some code. Is this the proper way to query this object?

if(!tmp.Any(p => p.ToLower().Contains("bar") || p.ToLower().Contains("baz"))
 doSomething(); 

The || seems silly. Should I be using a regular expression here or is there an even better way to be doing this? ***Also note the values in tmp are like "bar=someValue" like a query string. This code works ok but I'm certain it can written better. Thanks for any tips of feedback.

5
  • 7
    Why does the || seem silly? You want to do something if either X or Y is true for any item. Seems entirely reasonable to me. Commented Nov 14, 2012 at 15:46
  • To me you code looks perfectly alright. If there are many items, I would create extension method to simplify the syntax. For upto 2/3 items I would go with this approach. Commented Nov 14, 2012 at 15:52
  • Yes Jon || is ok now, but what about when I need to look for more values beside bar or baz? I was looking for something that scales a little better. I like the intersection approaches but the values in tmp are in name=value format. Thanks! Commented Nov 14, 2012 at 15:54
  • This doesn't exactly answer your question, but it's actually faster to use p.IndexOf("bar", StringComparison.CurrentCultureIgnoreCase) < 0 and avoid the ToLower() call. Commented Nov 14, 2012 at 15:58
  • "This code works ok but I'm certain it can written better." -- to what end? Without knowing in what way something is inadequate, it is impossible to improve it. Commented Nov 14, 2012 at 16:02

3 Answers 3

4

Any better? I don't know but should work.

if(!tmp.Select(x => x.Split('=')[0])
                    .Intersect(new[] { "foo", "baz" }, 
                               StringComparer.InvariantCultureIgnoreCase).Any())
    doSomething();
Sign up to request clarification or add additional context in comments.

5 Comments

but he also says that the strings are in form "bar=someValue".
yes the code works as is, it just seems inefficient is all. I was thinking of this perhaps? !tmp.Any(p => Regex.IsMatch(p, @"^(foo|baz)")
Yes, its right now, but can you please explain that how it is better then tmp.Any(p => p.ToLower().Contains("bar") || p.ToLower().Contains("baz"))
Think you might be missing a !.
The existing one seems at least more elegant.
1

You can use nested Any with StringComparison overload of IndexOf:

string[] source = { "hi=there", "hello=world", "foo=bar" };
string[] exclude = { "baz", "bar" };

if (!source.Any(src => 
        exclude.Any(exl =>  
            src.IndexOf(exl, StringComparison.InvariantCultureIgnoreCase) >= 0))) 
    doSomething();

Or packaged as an extension method:

public static class StringExtensions {
    public static bool ContainsAny(
        this IEnumerable<string> source,
        IEnumerable<string> target,
        StringComparison comparisonType = StringComparison.InvariantCultureIgnoreCase) {
        return source.Any(xsource => target.Any(
                xtarget => xsource.IndexOf(xtarget, comparisonType) >= 0));
    }
}


// Later ...
if (!source.ContainsAny(exclude))
    doSomething();

Comments

1

I don't think there is anything wrong with your existing code; though it could be slightly modified to avoid an extra ToLower() call:

var exists = tmp.Any(p => 
{ 
    var s = p.ToLower(); 
    return s.Contains("bar") || s.Contains("baz");
});
if(!exists) doSomething(); 

If your search terms can be numerous, something like this might work better:

var terms = new string[] {"bar", "baz", "foo", "boo", ...};
var exists = tmp.Any(p => terms.Any(t => p.ToLower().Contains(t)));
if(!exists) doSomething();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.