Получение индекса повторяющихся элементов в списке в 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 для списков находится здесь. Метод расширения списка Где здесь.
Оба из них будут делать именно то, что вы хотите, и они довольно просты в использовании. В Интернете есть множество примеров каждого из них, но если вам нужна помощь в их использовании, просто дайте мне знать.