Найти элемент в списке по LINQ?

Здесь у меня есть простой пример, чтобы найти элемент в списке строк. Обычно я использую для цикла или анонимного делегата сделать это следующим образом:

int GetItemIndex(string search)
{
   int found = -1;
   if ( _list != null )
   {
     foreach (string item in _list) // _list is an instance of List<string>
     { 
        found++;
        if ( string.Equals(search, item) )
        {
           break;
        }
      }
      /* use anonymous delegate
      string foundItem = _list.Find( delegate(string item) {
         found++;
         return string.Equals(search, item);
      });
      */
   }
   return found;
}

LINQ для меня новичок. Мне любопытно, могу ли я использовать LINQ для поиска элемента в списке? Как возможно?

Ответ 1

Есть несколько способов (обратите внимание, что это не полный список).

1) Single вернет единственный результат, но будет генерировать исключение, если он не найдет ничего или больше, чем один (который может или не может быть тем, что вы хотите):

string search = "lookforme";
List<string> myList = new List<string>();
string result = myList.Single(s => s == search);

Примечание SingleOrDefault() будет вести себя одинаково, за исключением того, что будет возвращать значение null для ссылочных типов или значение по умолчанию для типов значений вместо того, чтобы бросать исключение.

2) Где вернет все элементы, соответствующие вашим критериям, поэтому вы можете получить IEnumerable с одним элементом

IEnumerable<string> results = myList.Where(s => s == search);

3) Первый вернет первый элемент, который соответствует вашим критериям:

string result = myList.First(s => s == search);

Примечание FirstOrDefault() будет вести себя одинаково, за исключением того, что оно вернет null для ссылочных типов или значение по умолчанию для типов значений вместо того, чтобы выбрасывать исключение.

Ответ 2

Если вам нужен индекс элемента, это сделает это:

int index = list.Select((item, i) => new { Item = item, Index = i })
                .First(x => x.Item == search).Index;

// or
var tagged = list.Select((item, i) => new { Item = item, Index = i });
int index = (from pair in tagged
            where pair.Item == search
            select pair.Index).First();

Вы не можете избавиться от лямбда в первом проходе.

Обратите внимание, что это произойдет, если элемент не существует. Это решает проблему, используя nullable ints:

var tagged = list.Select((item, i) => new { Item = item, Index = (int?)i });
int? index = (from pair in tagged
            where pair.Item == search
            select pair.Index).FirstOrDefault();

Если вам нужен элемент:

// Throws if not found
var item = list.First(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).First();

// Null if not found
var item = list.FirstOrDefault(item => item == search);
// or
var item = (from item in list
            where item == search
            select item).FirstOrDefault();

Если вы хотите подсчитать количество элементов, которые соответствуют:

int count = list.Count(item => item == search);
// or
int count = (from item in list
            where item == search
            select item).Count();

Если вам нужны все элементы, которые соответствуют:

var items = list.Where(item => item == search);
// or
var items = from item in list
            where item == search
            select item;

И не забудьте проверить список для null в любом из этих случаев.

Или используйте (list ?? Enumerable.Empty<string>()) вместо list.

Спасибо Павлу за помощь в комментариях.

Ответ 3

Если это действительно List<string>, вам не нужен LINQ, просто используйте:

int GetItemIndex(string search)
{
    return _list == null ? -1 : _list.IndexOf(search);
}

Если вы ищете предмет, попробуйте:

string GetItem(string search)
{
    return _list == null ? null : _list.FirstOrDefault(s => s.Equals(search));
}

Ответ 4

Вы хотите элемент в списке или сам фактический элемент (предположительно сам элемент).

Вот вам несколько вариантов:

string result = _list.First(s => s == search);

string result = (from s in _list
                 where s == search
                 select s).Single();

string result = _list.Find(search);

int result = _list.IndexOf(search);

Ответ 5

Этот метод проще и безопаснее

var lOrders = new List<string>();

bool insertOrderNew = lOrders.Find(r => r == "1234") == null ? true : false

Ответ 6

Как насчет IndexOf?

Ищет указанный объект и возвращает индекс первого вхождения в списке

Например

> var boys = new List<string>{"Harry", "Ron", "Neville"};  
> boys.IndexOf("Neville")  
2
> boys[2] == "Neville"
True

Обратите внимание, что он возвращает -1, если значение не встречается в списке

> boys.IndexOf("Hermione")  
-1

Ответ 7

Я использовал словарь, который является своего рода индексированным списком, который даст мне именно то, что я хочу, когда захочу.

Dictionary<string, int> margins = new Dictionary<string, int>();
margins.Add("left", 10);
margins.Add("right", 10);
margins.Add("top", 20);
margins.Add("bottom", 30);

Всякий раз, когда я хочу получить доступ к моим значениям полей, например, я адресую свой словарь:

int xStartPos = margins["left"];
int xLimitPos = margins["right"];
int yStartPos = margins["top"];
int yLimitPos = margins["bottom"];

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

Ответ 8

Вот один из способов переписать ваш метод для использования LINQ:

public static int GetItemIndex(string search)
{
    List<string> _list = new List<string>() { "one", "two", "three" };

    var result = _list.Select((Value, Index) => new { Value, Index })
            .SingleOrDefault(l => l.Value == search);

    return result == null ? -1 : result.Index;
}

Таким образом, называя это

GetItemIndex("two") вернет 1,

а также

GetItemIndex("notthere") вернет -1.

Ссылка: linqsamples.com

Ответ 9

Попробуйте этот код:

return context.EntitytableName.AsEnumerable().Find(p => p.LoginID.Equals(loginID) && p.Password.Equals(password)).Select(p => new ModelTableName{ FirstName = p.FirstName, UserID = p.UserID });

Ответ 10

Это поможет вам получить первое или значение по умолчанию в вашем поиске в списке Linq

var results = _List.Where(item => item == search).FirstOrDefault();

В этом поиске будет найдено первое или значение по умолчанию, которое оно вернет.

Ответ 11

Если нам нужно найти элемент из списка, мы можем использовать метод расширений Find и FindAll, но между ними существует небольшая разница. Вот пример.

 List<int> items = new List<int>() { 10, 9, 8, 4, 8, 7, 8 };

  // It will return only one 8 as Find returns only the first occurrence of matched elements.
     var result = items.Find(ls => ls == 8);      
 // this will returns three {8,8,8} as FindAll returns all the matched elements.
      var result1 = items.FindAll(ls => ls == 8); 

Ответ 12

Вы хотите найти объект в списке объектов.

Это поможет вам получить первое значение или значение по умолчанию в поиске Linq List.

var item = list.FirstOrDefault(items =>  items.Reference == ent.BackToBackExternalReferenceId);

или же

var item = (from items in list
    where items.Reference == ent.BackToBackExternalReferenceId
    select items).FirstOrDefault();