des
des

Reputation: 67

Assign variable and check it within an IF evaluation

I doubt this can be done but I'll ask anyway since it would make my code much more readable.

I have to control a large string for various substrings and elaborate it in different ways depending on the substring found.

At the moment I have a nested if like

position = mystring.IndexOf("my substring")
if (position>0)
{
    position = mystring.IndexOf("somestring", position);
    [...]
}
else
{
    position = mystring.IndexOf("my substring2")
    if (position>0)
    {
        position = mystring.IndexOf("somestring2", position);
        [...]
    }
    else {...}
}

The only other way I can think of doing this is double casting the IndexOf function:

if (mystring.IndexOf("my substring")>0)
{

    position = mystring.IndexOf("somestring", mystring.IndexOf("my substring"));
    [...]
}
else if (mystring.IndexOf(mysubstring2)>0)
{
    position = mystring.IndexOf("somestring2", mystring.IndexOf("my substring2"));
    [...]
}
else {...}

Is there a way to check the IndexOf() result and assign it to a variable all within the if() statement?

Something on the line of

if ((position = mystring.IndexOf("my substring")) AndAlso position > 0) { ... }

or any tip on having such a piece of code handled better?

Upvotes: 2

Views: 7094

Answers (4)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

Technically, you can put it as

int position;

if ((position = mystring.IndexOf("my substring")) > 0)
{

    // Note, that you should use position + "my substring".Length if 
    // "somestring" can't be part of previous match
    position = mystring.IndexOf("somestring", position);
    [...]
}
else if ((position = mystring.IndexOf(mysubstring2)) > 0)
{
    position = mystring.IndexOf("somestring2", position);
    [...]
}
else {...}

However, I suggest extracting a method:

private static bool FindMany(string source, out int lastIndex, params string[] toFind) {
  if (null == toFind)
    throw new ArgumentNullException(nameof(toFind));

  lastIndex = -1;
  int result = -1;

  if (string.IsNullOrEmpty(source))
    return false;

  int index = 0;

  for (int i = 0; i < toFind.Length; ++i) {
    result = source.IndexOf(toFind[i], index);

    index += toFind[i].Length;

    if (index < 0)
      return false;          
  }

  lastIndex = result;

  return true;
}

Which you can use as

int position;

if (FindMany(mystring, out position, "my substring", "somestring") {
  // "my substring" found

  if (position >= 0) {
    // "somestring" is found as well; its index - position   
    ...
  }
  else {
    // only "my substring" has been found
  }
}
else if (FindMany(mystring, out position, "my substring2", "somestring2") {
  // "my substring2" found

  if (position >= 0) {
    // "somestring2" is found  
    ...
  }
}

Upvotes: 1

default
default

Reputation: 11635

this does sound like a job for regex with positive lookbehind: a positive lookbehind makes sure that the string inside (?<=) exists prior to the other string

Together with a TryGet..approach with an out parameter it can almost become a one liner.

However, Dmitrys solution is a tad more future proof, since it accepts multiple input strings to search for. Building that regex could prove unmaintainable

https://dotnetfiddle.net/D5WFyx

using System;
using System.Text.RegularExpressions;

public static void Main()
{
    string input = "here is my substring and then somestring";

    int position;
    if (TryGetIndex(input, "(?<=my substring.*)somestring", out position)){
        Console.WriteLine($"somestring index: {position}");
    }
    else if (TryGetIndex(input, "(?<=other substring.*)otherstring", out position)) {
        Console.WriteLine($"otherstring index: {position}");
    }

    bool TryGetIndex(string input, string pattern, out int position){
        var match = Regex.Match(input, pattern);
        if (match.Success){
            position = match.Index;
            return true;
        }
        position = -1;
        return false;
    }
}

Upvotes: 0

MindSwipe
MindSwipe

Reputation: 7855

Yes you can do it, like so:

var myString = "Hello World";
int pos;

if ((pos = myString.IndexOf("World")) >= 0)
{
    Console.WriteLine(pos); // prints 6
}
else if ((pos = myString.IndexOf("Some Other Substring")) >= 0)
{
    // Do whatever
}

Note that I'm using myString.IndexOf(...) >= 0 as the index of the substring could be 0 (i.e starting at the first character), and the IndexOf method returns -1 if none was found

But you could rather just use string.Contains like so:

var myString = "Hello World";

if (myString.Contains("World"))
{
    // Do whatever
}
else if (myString.Contains("Some Other Substring"))
{
    // Do whatever
}

This is better if you don't explicitly need the location of the substring, but if you do, use the first one

Upvotes: 4

crucifery
crucifery

Reputation: 458

Use Contains() and, in addition, use IndexOf()separately if you really need to have a position by some reason. if (mystring.Contains("my substring")) { ... }

Upvotes: 0

Related Questions