0

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);
  
}
aTubOfAdam
  • 91
  • 1
  • 7
  • 1
    There are a few ways to do this. Can you [edit] and add your attempt so we can focus on fixing that? – 001 Nov 24 '21 at 13:00
  • 1
    You must determine what consists of a "name". Is that alphanumeric characters, hyphens and underscores (A-Z, 0-9, -, \_)? Then you could use a RegEx like `\*[A-Z0-9\-_]+` to detect names. If you'd code that yourself, it would look like _"taking the first delimited * and ending when we reach a character that isn't a letter, number, underscore or hyphen"_. If that didn't work and you want help fixing it, then show it. – CodeCaster Nov 24 '21 at 13:00
  • I have added my terrible attempt so far. – aTubOfAdam Nov 24 '21 at 14:30

3 Answers3

0

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
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
0

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 "";
}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • When I tried to compile this solution, I found that I was getting this error: Index was outside the bounds of the array. – aTubOfAdam Nov 24 '21 at 18:29
  • You won't get that at compile-time, only at run-tme. Can you show your implementation and test code? – Idle_Mind Nov 24 '21 at 18:35
0

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);
}
001
  • 13,291
  • 5
  • 35
  • 66