Метод String.IndexOf () работает не так, как я ожидал.

Я ожидал, что совпадение не будет найдено, поскольку точного слова вы нет в str.

string str = "I am your Friend";
int index = str.IndexOf("you",0,StringComparison.OrdinalIgnoreCase);
Console.WriteLine(index);

Выход: 5

Мой ожидаемый результат -1, потому что строка не содержит вас .

-1
Nilesh Agotariya 31 Май 2019 в 07:58

2 ответа

Лучший ответ

Проблема, с которой вы сталкиваетесь, заключается в том, что IndexOf соответствует одному символу или последовательности символов (строка поиска) в большей строке. Поэтому «Я твой друг» содержит последовательность «ты». Чтобы соответствовать только словам, вы должны рассмотреть вещи на уровне слов.

Например, вы можете использовать регулярные выражения для соответствия границ слова:

private static int IndexOfWord(string val, int startAt, string search)
{
    // escape the match expression in case it contains any characters meaningful
    // to regular expressions, and then create an expression with the \b boundary
    // characters
    var escapedMatch = string.Format(@"\b{0}\b", Regex.Escape(search));

    // create a case-sensitive regular expression object using the pattern
    var exp = new Regex(escapedMatch, RegexOptions.IgnoreCase);

    // perform the match from the start position
    var match = exp.Match(val, startAt);

    // if it's successful, return the match index
    if (match.Success)
    {
        return match.Index;
    }

    // if it's unsuccessful, return -1
    return -1;
}

// overload without startAt, for when you just want to start from the beginning
private static int IndexOfWord(string val, string search)
{
    return IndexOfWord(val, 0, search);
}

В вашем примере вы попытаетесь найти соответствие \byou\b, что из-за граничных требований не будет соответствовать your.

Попробуйте онлайн

Подробнее о границах слов читайте в Регулярных выражениях здесь.

7
John 31 Май 2019 в 05:14

you является допустимой подстрокой I am your Friend. Если вы хотите узнать, содержится ли слово в строке, вы можете разобрать строку с помощью метода Split.

char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
string[] words = text.Split(delimiterChars);

А потом загляните внутрь массива. Или превратить его в более удобную для поиска структуру данных.

Если вы хотите выполнить поиск без учета регистра, вы можете использовать следующий код:

char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
string text = "I am your Friend";
// HasSet allows faster lookups in case of big strings
var words = text.Split(delimiterChars).ToHashSet(StringComparer.OrdinalIgnoreCase);
Console.WriteLine(words.Contains("you"));
Console.WriteLine(words.Contains("friend"));

Ложные
Правда


Создав словарь, как в следующем фрагменте кода, вы можете быстро проверить все позиции для всех слов.

char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
string text = "i am your friend. I Am Your Friend.";
var words = text.Split(delimiterChars);
var dict = new Dictionary<string, List<int>>(StringComparer.InvariantCultureIgnoreCase);
for (int i = 0; i < words.Length; ++i)
{
    if (dict.ContainsKey(words[i])) dict[words[i]].Add(i);
    else dict[words[i]] = new List<int>() { i };
}

Console.WriteLine("youR: ");
dict["youR"].ForEach(i => Console.WriteLine("\t{0}", i));
Console.WriteLine("friend");
dict["friend"].ForEach(i => Console.WriteLine("\t{0}", i));
youR:   
        2   
        7   
friend   
        3   
        8
2
Yola 31 Май 2019 в 06:03
56388874