Home > Net >  Method that takes a message and index, creates a substring using the index
Method that takes a message and index, creates a substring using the index

Time:11-25

Problem: I want to write a method that takes a message/index pair like this:

("Hello, I am *Name1, how are you doing *Name2?", 2)

The index refers to the asterisk delimited name in the message. So if the index is 1, it should refer to *Name1, if it's 2 it should refer to *Name2.

The method should return just the name with the asterisk (*Name2).

I have attempted to play around with substrings, taking the first delimited * and ending when we reach a character that isn't a letter, number, underscore or hyphen, but the logic just isn't setting in.

I know this is similar to a few problems on SO but I can't find anything this specific. Any help is appreciated.

This is what's left of my very vague attempt so far. Based on this thread:

public string GetIndexedNames(string message, int index)
{
    int strStart = message.IndexOf("@")   "@".Length;
    int strEnd = message.LastIndexOf(" ");

    String result = message.Substring(strStart, strEnd - strStart);
  
}

CodePudding user response:

If you want to do it the old school way, then something like:

public static void Main(string[] args)
{
    string message = "Hello, I am *Name1, how are you doing *Name2?";
    string name1 = GetIndexedNames(message, "*", 1);
    string name2 = GetIndexedNames(message, "*", 2);
    Console.WriteLine(message);
    Console.WriteLine(name1);
    Console.WriteLine(name2);
    Console.ReadLine();
}

public static string GetIndexedNames(string message, string singleCharDelimiter, int index)
{
    string valid = "abcdefghijlmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
    string[] parts = message.Split(singleCharDelimiter.ToArray());
    if (parts.Length >= index)
    {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < parts[index].Length; i  )
        {
            string character = parts[index].Substring(i, 1);
            if (valid.Contains(character))
            {
                sb.Append(character);
            }
            else
            {
                return sb.ToString();
            }
        }
        return sb.ToString();
    }
    return "";
}

CodePudding user response:

You can try using regular expressions to match the names. Assuming that name is a sequence of word characters (letters or digits):

 using System.Linq;
 using System.Text.RegularExpressions; 

 ...

 // Either name with asterisk *Name or null
 // index is 1-based
 private static ObtainName(string source, int index) => Regex
   .Matches(source, @"\*\w ")
   .Cast<Match>()
   .Select(match => match.Value)
   .Distinct() // in case the same name repeats several times
   .ElementAtOrDefault(index - 1); 

Demo:

 string name = ObtainName(
   "Hello, I am *Name1, how are you doing *Name2?", 2);

 Console.Write(name);

Outcome:

 *Name2

CodePudding user response:

Perhaps not the most elegant solution, but if you want to use IndexOf, use a loop:

public static string GetIndexedNames(string message, int index, char marker='*')
{
    int lastFound = 0;
    for (int i = 0; i < index; i  ) {
        lastFound = message.IndexOf(marker, lastFound 1);
        if (lastFound == -1) return null;
    }
    var space = message.IndexOf(' ', lastFound);
    return space == -1 ? message.Substring(lastFound) : message.Substring(lastFound, space - lastFound);
}
  • Related