32

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.

Liam
  • 27,717
  • 28
  • 128
  • 190
neven
  • 323
  • 1
  • 3
  • 4
  • Why wouldn't you want to use the || operator? This is what it is for. If can think of solutions which don't use EndsWith, but they still use the || operator – Stewart May 09 '10 at 07:02
  • 4
    Ridiculous Restrictions = Homework – Ignacio Vazquez-Abrams May 09 '10 at 07:02
  • 4
    @stewart : If i have 20 strings to check,I have to use || operator 19 times. – neven May 09 '10 at 07:07
  • 4
    I wish people asking homework questions would tag them as such. It is such a bizarre question otherwise. The right answer as far as I am concerned is "Write it with || for goodness sake." – Stewart May 09 '10 at 07:12
  • @neven: Will all the strings you have to check be only one character long? – Mark Byers May 09 '10 at 07:13
  • 1
    @neven - if you have 20 strings to check you should have said. Your question implies a small fixed grammar. If you have a larger grammar it changes the answer. Even RegExes won't help with 20 strings to check. Hint - try a table and a for loop – Stewart May 09 '10 at 07:14
  • @neven: You should edit your question instead of hiding important information in comments. I have done this for you on this occasion, but please remember this in future. – Mark Byers May 09 '10 at 07:17
  • @Stewart & @Mark Byers : Next time I'll post all the required info.As my requirements changed,I added them in the comments.Next time I'll be more clear with my question. – neven May 09 '10 at 07:44

9 Answers9

59

If you are using .NET 3.5 (and above) then it is quite easy with LINQ:

string test = "foo+";
string[] operators = { "+", "-", "*", "/" };
bool result = operators.Any(x => test.EndsWith(x));
kiafiore
  • 1,071
  • 2
  • 11
  • 27
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 2
    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 May 09 '10 at 07:19
  • Wouldn't this be very slow? It will certainly generate a lot of code. – Stewart May 09 '10 at 07:29
  • @Stewart: Could you explain how this generates a lot of code? – Mark Byers May 09 '10 at 07:44
  • @ck: Regular expressions is a hammer. LINQ is a whole tool box. – Mark Byers May 09 '10 at 07:48
  • @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 May 09 '10 at 08:01
  • 1
    @Stewart That's all nonsense. The only lambda expressions LINQ uses are the ones you type ... in this case `x => test.EndsWith(x)` Anyway, generally, a premature concern with efficiency is incompetent. – Jim Balter Oct 29 '13 at 03:30
  • 2
    A slightly shorter version of this would be `bool result = operators.Any(test.EndsWith);` – MrRoboto Jul 06 '20 at 16:57
10

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

if (Regex.IsMatch(mystring, @"[-+*/]$")) {
  ...
}
Max Shawabkeh
  • 37,799
  • 10
  • 82
  • 91
  • 4
    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 May 09 '10 at 07:16
  • @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 May 09 '10 at 07:29
  • 3
    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. – mpen May 09 '10 at 07:37
  • 2
    "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 May 09 '10 at 07:59
  • 1
    "I've never learned them properly." -- That's your problem; it has no bearing on this solution. "if the next operator to be parsed is ||, this solution just got enourmously complex" -- no, it didn't, and regex is still simpler than other solutions. "compiling and parsing the regex isn't free of course" -- this is a constant regex, so it can be parsed and compiled exactly once per execution. If *that* was your complaint, then the answer could be changed to use a static initializer. – Jim Balter Oct 29 '13 at 03:13
5
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
  • 135,331
  • 41
  • 252
  • 292
3

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
Serge S.
  • 4,855
  • 3
  • 42
  • 46
3

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
  • 3,978
  • 17
  • 20
  • 1
    Yessir. I'd say regexes, or this answer. – mpen May 09 '10 at 07:40
  • 1
    You don't like regexes, you don't like LINQ ... not because of any problem with them, but because you can't read them. That's entirely your problem. – Jim Balter Oct 29 '13 at 03:18
2

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
  • 30,133
  • 4
  • 83
  • 114
0

Is a regex expression not an option

Mark Pearl
  • 7,573
  • 10
  • 47
  • 57
0

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.
cjk
  • 45,739
  • 9
  • 81
  • 112
0

Using String.IndexOf(String):

str.Lenght > 0 ? "+-*/".IndexOf(str[str.Lenght - 1]) != -1 : false
Serge S.
  • 4,855
  • 3
  • 42
  • 46