在LINQ列表中查找项目?


226

在这里,我有一个简单的示例,可以在字符串列表中找到一个项目。通常我使用for循环或匿名委托来做到这一点:

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在列表中查找项目?如果可能怎么办?


那很棒。但是,这些都是lamda表达方式。我在这里用一个简单的清单。该列表可能是具有多个属性的类,并且其中一些用于搜索。因此,任何LINQ方式都可以像“从........中...选择...”中进行搜索
David.Chu.ca 2009年

不,对不起。这些方法中的大多数(First,Single,Any等)都无法直接转换为该形式。
R. Martinho Fernandes

没关系,实际上您可以在少数情况下摆脱lambdas的影响
R. Martinho Fernandes

好答案!我只想从枚举案例中了解LINQ搜索。
David.Chu.ca,2009年

Answers:


478

有几种方法(请注意,这不是完整的列表)。

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)First将返回符合您条件的第一项:

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

注意FirstOrDefault()将具有相同的行为,除了它将为引用类型返回null或为值类型返回默认值,而不是引发异常。


35
好答案。我发现SingleOrDefault是我的选择答案-与Single相同,但是如果找不到它,则返回“ null”。
艾迪·帕克

2
我不知道Single()或SingleOrDefault()。很有用。
draconis 2014年

可以将这些方法与其他集合太喜欢使用ReadOnlyCollectionObservableCollection
yellavon

@yellavon这些是实现IEnumerable<T>或实现的任何类型的扩展方法,或者IQueryable<T>
Rex M

4
使用SingleOrDefault时要注意的一件事是,如果列表中有多个匹配项,它将引发异常,因此它必须遍历每个项目,一旦找到第一个匹配项,FirstOrDefault将停止搜索。msdn.microsoft.com/zh-CN/library/bb342451(v=vs.110).aspx
DavidWainwright

73

如果要元素的索引,可以这样做:

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();

在第一遍中,您无法摆脱lambda。

请注意,如果该项目不存在,则会抛出该异常。这可以通过使用可为null的int来解决此问题:

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

感谢Pavel在评论中提供的帮助。


2
两点。首先,没有真正的必要在string.Equals这里使用- ==。其次,我还要提到FirstOrDefault(对于项目可能不存在的情况),并Select使用索引来覆盖需要项目索引的情况(因为它在问题本身的示例中)。
帕维尔米纳夫

我还不开心 在我的示例中没有-1索引(未找到)。有什么建议吗?
R. Martinho Fernandes

除了首先检查是否存在。
R. Martinho Fernandes

我是否需要先检查list是否为null?
David.Chu.ca,2009年

ArgumentNullException如果源为空,则选择引发
R. Martinho Fernandes

13

如果确实是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));
}

1
按照第一个示例的逻辑,我们可以使用_list.Find(search)第二个示例。
jwg

12

您想要列表中的项目还是实际项目本身(将假定项目本身)。

这里有很多选项供您选择:

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);

哇...有些人超快触发了它;)
Kelsey

索引作为返回值怎么样?
David.Chu.ca,2009年

并且我是否需要检查_list是否以_list中的from ..形式出现为空...?
David.Chu.ca,2009年

6

此方法更简单,更安全

var lOrders = new List<string>();

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


1
我认为我们甚至不需要true : false下面的工具就可以正常工作 bool insertOrderNew = lOrders.Find(r => r == "1234") == null;
Vbp

5

怎么IndexOf

搜索指定的对象并返回列表中第一个匹配项的索引

例如

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

请注意,如果列表中未出现该值,则返回-1

> boys.IndexOf("Hermione")  
-1

2

我曾经使用过字典,它是某种索引列表,可以在需要时准确显示我想要的内容。

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"];

因此,根据您的工作,字典可能会有用。


一个不同问题的好答案。
jwg

2

这是重写方法以使用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


1

试试这个代码:

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

1

如果需要从列表中查找元素,则可以使用Findand 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); 

1

这将帮助您获取Linq List搜索中的第一个值或默认值

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

该搜索将找到它将返回的第一个或默认值。


0

您要搜索对象列表中的对象。

这将帮助您在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();

0

您可以将FirstOfDefault与Where Linq扩展一起使用,以从IEnumerable获取MessageAction类。雷姆

var action = Message.Actions.Where(e => e.targetByName == className).FirstOrDefault();

哪里

列出动作{ 组; }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.