views:

156

answers:

9
+4  Q: 

string.EndsWith()

I need to check in string.Endswith("") from any of the following operators: "+,-,*,/"

If I have 20 operators I don't want to use "||" operator 19 times.

A: 

Is a regex expression not an option

Mark Pearl
+5  A: 

Although a simple example like that is probably good enough using ||, you can also use Regex for it:

if (Regex.IsMatch(mystring, @"[-+*/]$")) {
  ...
}
Max Shawabkeh
I personally hesitate to ever recommend RegEx. For the problem as presented this is just about the slowest possible solution, as well as being the most complex.
Stewart
@Stewart: I wouldn't go as far as hesitating to recommend regex for any task, but I have to agree that it's not the simplest method here. With regex it is easy to introduce an error, for example in this case if the OP inserts more characters they should be careful to enter them at the end of the list. If they are added at the start the hyphen would become a range which could be a hard to find error if you're not used to regex syntax.
Mark Byers
You know, most people jump on regexes every time a string problem arises, but this is one situation where I think a regex actually *is* clean, concise, easy to understand, and easy to maintain.......if you know regexes.
Mark
"If you know regexes" says it all. My problem with Regexes is twofold. I've never learned them properly. I can use them if I have to, but I don't spend most of my time munging strings so I never learned them. This means that when I'm reviewing or reading or debugging code, I have to stop and read a line containing a Regex several times. Lines that have to be read several times are a great way of hiding errors. Also, if the next operator to be parsed is "||", this solution just got enourmously complex. And compiling and parsing the regex isn't free of course.
Stewart
+1  A: 

If you really want to, you can use De Morgan's laws to replace x || y in your code. One version says:

!(x || y) == !x && !y

If you want to have the same result, we just need to negate the entire expression twice:

x || y == !!(x || y) == !(!x && !y)
Porges
Totally correct and working, but I wouldn't like to be reading that in 6 months time looking for a bug.
Stewart
+6  A: 

If you are using .NET 3.5 then it is quite easy with LINQ:

string test = "foo+";
string[] operators = { "+", "-", "*", "/" };
bool result = operators.Any(x => test.EndsWith(x));
Mark Byers
LINQ is always the correct hammer for the job :)
ck
I find it clearer to just use an array when initializing things like that: var operators = new [] {"+", "-", "*", "/"};`. Or just: bool result = new [] {"+", "-", "*", "/"}.Any(x => test.EndsWith(x));`
Svish
@Svish: Changed to array. :)
Mark Byers
Wouldn't this be very slow? It will certainly generate a lot of code.
Stewart
@Stewart: Could you explain how this generates a lot of code?
Mark Byers
@ck: Regular expressions is a hammer. LINQ is a whole tool box.
Mark Byers
@Mark Byers - good point - in this case it doesn't really, but in general linq uses a lot of lambdas, typically with closure objects, and a lot of generic types fly past which you don't see. None of those objects is free, and none of them are visibly in the line of code you show.
Stewart
+2  A: 

Test the last char of the string using String.IndexOfAny(Char[], Int32) method (assuming str is your variable):

str.IndexOfAny(new char[] {'+', '-', '*', '/'}, str.Length - 1)

Complete expression:

str.Lenght > 0 ? str.IndexOfAny(new char[] {'+', '-', '*', '/'}, str.Length - 1) != -1 : false
SergeanT
Nice, but it assumes that all operator consist of only one character.
Mark Byers
Yeah, it's a problem. It's needed to test lenght of the string is >= 1.
SergeanT
A: 

Given the complete lack of context, would this solution that is worse than using an easy || operator be of use:

Boolean check = false;
if (myString.EndsWith("+"))
     check = true;

if (!check && myString.EndsWith("-"))
     check = true;

if (!check && myString.EndsWith("/"))
     check = true;

etc.
ck
A: 
string s = "Hello World +";
string endChars = "+-*/";

Using a function:

private bool EndsWithAny(string s, params char[] chars)
{
    foreach (char c in chars)
    {
        if (s.EndsWith(c.ToString()))
            return true;
    }
    return false;
}

bool endsWithAny = EndsWithAny(s, endChars.ToCharArray()); //use an array
bool endsWithAny = EndsWithAny(s, '*', '/', '+', '-');     //or this syntax

Using LINQ:

bool endsWithAny = endChars.Contains(s.Last());

Using TrimEnd:

bool endsWithAny = s.TrimEnd(endChars.ToCharArray()).Length < s.Length;
// als possible s.TrimEnd(endChars.ToCharArray()) != s;
Kobi
+1  A: 

How about:-

string input = .....;
string[] matches = { ...... whatever ...... };

foreach (string match in matches)
{
    if (input.EndsWith(match))
        return true;
}

I know it is dreadfully old school to avoid LINQ in this context, but one day you will need to read this code. I am absolutely sure that LINQ has its uses (maybe i'll find them one day) but i am quite sure it is not meant to replace the four lines of code above.

Stewart
Yessir. I'd say regexes, or this answer.
Mark
A: 

Using String.IndexOf(String):

str.Lenght > 0 ? "+-*/".IndexOf(str[str.Lenght - 1]) != -1 : false
SergeanT