Получение индекса повторяющихся элементов в списке в C#

Я ищу способ получить индекс всех элементов в списке из поиска по ключевым словам в списке. Так, например, мой список имеет:

Hello World
Programming Rocks
Hello
Hello World
I love C#
Hello

Теперь из этого списка строк я хочу получить все индексы элементов, которые говорят Hello World. Я пробовал следующее, но он возвращает только первый найденный индекс, который имеет мои критерии поиска:

    for (int i = 0; i< searchInList.Count; i++)
        foundHelloWorld[i] = searchInList.IndexOf("Hello World");

Кто-нибудь знает способ сделать это?

Спасибо

4 ответа

Решение
searchInList.Select((value, index) => new {value, index})
    .Where(a => string.Equals(a.value, "Hello World"))
    .Select(a => a.index)

Если вы пытаетесь искать больше, чем просто "Hello World"Вы могли бы сделать

searchInList.Select((value, index) => new {value, index})
    .Where(a => stringsToSearchFor.Any(s => string.Equals(a.value, s)))
    .Select(a => a.index)

Поскольку вы знаете, что ищете ВСЕ вхождения, и, следовательно, вам все равно придется пройти по всему списку, вы получите большую читабельность по сравнению с использованием IndexOf, просто проверив каждый элемент самостоятельно:

var i=0;
foreach(var value in searchInList)
{
   if(value == "Hello World")
      foundHelloWorld.Add(i); //foundHelloWorld must be an IList

   i++;
}

Вы также можете использовать перегрузку метода Linq Select, которая включает индекс элемента в исходную коллекцию; это должно быть легко читаемым (и, следовательно, поддерживаемым) для опытных программистов Linq:

foundHelloWorld = searchInList
                     .Select((v,i)=>new {Index = i, Value = v})
                     .Where(x=>x.Value == "Hello World")
                     .Select(x=>x.Index)
                     .ToList();

Приведенный выше код берет список и преобразует строку в простой анонимный тип, включающий место каждого элемента в исходном списке. Затем он фильтрует только до соответствующих элементов, а затем проецирует индекс (который не изменился в результате фильтрации) в новый объект List. Однако все это преобразование замедлит выполнение этого решения, поскольку этот оператор будет многократно проходить по всему списку.

Немного некрасиво, но сработает

    var searchInList = new List<string>();

//Populate your list

    string stringToLookUp= "Hello world";
    var foundHelloWorldIndexes = new List<int>();

    for (int i = 0; i < searchInList.Count; i++)
        if (searchInList[i].Equals(stringToLookUp))
            foundHelloWorldIndexes.Add(i);

Метод FindAll для списков находится здесь. Метод расширения списка Где здесь.

Оба из них будут делать именно то, что вы хотите, и они довольно просты в использовании. В Интернете есть множество примеров каждого из них, но если вам нужна помощь в их использовании, просто дайте мне знать.

Другие вопросы по тегам