Уж больно мне не нравится вариант от
BasiC2k, по тому решил написать свой:
1. Чуть более компактный в плане памяти и количества кода, если нужно найти индекс один раз. + С проверкой, на отсутствие слова.
var array = new[] { "Картоновый человек", "Морковка белая", "секретный специалист " };
Console.WriteLine(FindIndexOfWord(array, "картоновый")); // 0
Console.WriteLine(FindIndexOfWord(array, "Бомбастер")); // -1
Console.WriteLine(FindIndexOfWord(array, "Специалист")); // 2
// В 1 проход. Если не нравится linq - можно одной кнопкой переписать на циклы и получится почти zero-allocation код.
static int FindIndexOfWord(string[] array, string word) =>
array
.Select((str, i) => (str.Split(' '), i))
.Where(x => x.Item1.Any(w => w.Equals(word, StringComparison.OrdinalIgnoreCase)))
.Select(x => x.Item2)
.Cast<int?>()
.FirstOrDefault() ?? -1;
2. Более быстрый, если нужно искать данные много раз и в больших массивах:
var array = new[] { "Картоновый человек", "Морковка белая", "секретный специалист " };
var index = new WordIndex(array);
Console.WriteLine(index.Find("картоновый")); //0
Console.WriteLine(index.Find("чикибамбони")); //-1;
// Поиск элемента в словаре по ключу выполняется за константное время, так что если нужно делать это часто и на больших массивах, то выгоднее 1 раз всё проиндексировать.
class WordIndex {
private readonly Dictionary<string, int> _cache;
public WordIndex(IEnumerable<string> seq) {
_cache = new Dictionary<string, int>();
var i = 0;
foreach(var str in seq) {
foreach(var word in str.Split(' ')) {
var key = word.ToUpperInvariant();
if(!_cache.ContainsKey(key)) {
_cache.Add(key, i);
}
}
i++;
}
}
public int Find(string word) =>
_cache.TryGetValue(word.ToUpperInvariant(), out var value)
? value
: -1;
}