【问题标题】:Find an item in a list by LINQ通过 LINQ 在列表中查找项目
【发布时间】:2010-11-13 14:56:37
【问题描述】:

这里我有一个简单的例子来在字符串列表中查找一个项目。通常我使用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 an anonymous delegate
      string foundItem = _list.Find( delegate(string item) {
         found++;
         return string.Equals(search, item);
      });
      */
   }
   return found;
}

LINQ 对我来说是新的。我可以使用 LINQ 在列表中查找项目吗?如果可以,怎么做?

【问题讨论】:

  • 太好了。但是,这些都是lamda的表达方式。我在这里使用一个简单的列表。该列表可能是一个具有多个属性的类,其中一些用于搜索。因此,任何 LINQ 搜索方式都可以像“从 .. in ... where... select...”
  • 不,抱歉。这些方法中的大多数(First、Single、Any、...)都不能直接翻译成那种形式。
  • 没关系,实际上你可以在少数情况下摆脱 lambdas...
  • 很好的答案!我只是想从枚举案例中体验一下LINQ搜索。

标签: c# linq


【解决方案1】:

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

  1. Single 将返回一个结果,但如果它没有找到或找到一个以上的结果(这可能是也可能不是您想要的),则会抛出异常:

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

请注意,SingleOrDefault() 的行为与此相同,只是它将为引用类型返回 null,或为值类型返回默认值,而不是引发异常。

  1. Where 将返回所有符合您条件的项目,因此您可能会得到一个带有一个元素的 IEnumerable

     IEnumerable<string> results = myList.Where(s => s == search);
    
  2. First 将返回符合您条件的第一个项目:

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

请注意,FirstOrDefault() 的行为与此相同,只是它将为引用类型返回 null,或为值类型返回默认值,而不是引发异常。

【讨论】:

  • 很好的答案。我发现 SingleOrDefault 是我选择的答案 - 与 Single 相同,但如果找不到则返回“null”。
  • 我不知道 Single() 或 SingleOrDefault()。非常有用。
  • 这些方法也可以与ReadOnlyCollectionObservableCollection 等其他集合一起使用吗?
  • @yellavon 这些是实现IEnumerable&lt;T&gt;IQueryable&lt;T&gt; 的任何类型的扩展方法
  • 使用 SingleOrDefault 需要注意的一点是,如果列表中有多个匹配项,它会引发异常,因此它必须遍历每个项目,一旦第一个匹配项,FirstOrDefault 将停止搜索成立。 msdn.microsoft.com/en-us/library/bb342451(v=vs.110).aspx
【解决方案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();

你无法在第一遍中摆脱 lambda。

请注意,如果该项目不存在,这将抛出。这通过使用可为空的整数来解决问题:

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&lt;string&gt;()) 代替list

【讨论】:

  • 两点。首先,这里没有真正需要使用string.Equals - == 没有错。其次,我还要提到FirstOrDefault(对于可能不存在项目的情况)和带有索引的Select,以涵盖需要项目索引的情况(因为它在问题本身的示例中)。
  • 我还不开心。在我的示例中没有 -1 索引(未找到)。有什么建议吗?
  • 除了先用 if 检查它是否存在。
  • 是否需要先检查list是否为空?
  • 如果源为空,则选择抛出ArgumentNullException
【解决方案3】:

如果确实是List&lt;string&gt;,则不需要 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));
}

【讨论】:

  • 按照第一个例子的逻辑,我们可以使用_list.Find(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);

【讨论】:

  • 索引作为返回值怎么样?
  • 我是否需要以 from .. in _list... 的形式检查 _list 是否为空?
【解决方案5】:

这种方法更简单更安全

var lOrders = new List<string>();

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

【讨论】:

  • 我认为我们甚至不需要下面的true : false 应该可以正常工作bool insertOrderNew = lOrders.Find(r =&gt; r == "1234") == null;
【解决方案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】:

    如果我们需要从列表中查找一个元素,那么我们可以使用FindFindAll扩展方法,但是它们之间有细微的差别。这是一个例子。

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

    【讨论】:

      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

        这将帮助您在 LINQ 列表搜索中获取第一个或默认值

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

        此搜索将找到第一个或默认值,并将返回。

        【讨论】:

          【解决方案11】:

          试试这个代码:

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

          【讨论】:

          • 也许把它分成几行?
          【解决方案12】:

          您想在对象列表中搜索一个对象。

          这将帮助您在 Linq 列表搜索中获得第一个或默认值。

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

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

          【讨论】:

          【解决方案13】:

          您可以将 FirstOfDefault 与 Where LINQ 扩展一起使用,以从 IEnumerable 获取 MessageAction 类。回忆

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

          在哪里

          List<MessageAction> Actions { get; set; }
          

          【讨论】:

            【解决方案14】:

            另一种检查 List 中元素是否存在的方法

            var result = myList.Exists(users => users.Equals("Vijai"))
            

            【讨论】:

              猜你喜欢
              • 2016-09-01
              • 2012-07-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多