检查列表是否包含包含字符串的元素并获取该元素


146

在寻找这个问题的答案时,我遇到了使用LINQ的类似问题,但是由于我不熟悉它,所以我无法完全理解它们(因此无法实现它们)。我基本上想要的是:

  1. 检查列表中的任何元素是否包含特定字符串。
  2. 如果是这样,请获取该元素。

老实说,我不知道该怎么做。我能想到的是这样(当然不起作用):

if (myList.Contains(myString))
    string element = myList.ElementAt(myList.IndexOf(myString));

我知道为什么它不起作用:

  • myList.Contains()不返回true,因为它将检查列表的整个元素是否与我指定的字符串匹配。
  • myList.IndexOf() 不会发现任何情况,因为再次检查情况是,它将检查与字符串匹配的元素。

仍然,我不知道如何解决这个问题,但是我认为我必须按照类似的问题中的建议使用LINQ。话虽如此,如果是这种情况,我想请回答者在他们的示例中向我解释LINQ的用法(正如我所说的,我在使用C#时并没有为此而烦恼)。在此先感谢大家(还有gal?)。

编辑:我想出了一个解决方案;只需遍历列表,检查当前元素是否包含字符串,然后将字符串设置为等于当前元素。我想知道,是否有比这更有效的方法?

string myString = "bla";
string element = "";

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}

正如我在回答中提到的那样,旧时尚循环(就像您的问题一样)几乎总是最快的。但是,如果您足够关心的话,可以进行性能测试。
麦凯2013年

列表中可能有多个包含string的字符串myString,在当前循环中,您将获得最后一个元素。是否要查找第一个或最后一个取决于您,如果只想查找第一个,则在找到项目后中断循环。
哈比卜2013年

Answers:


193

您应该可以在这里使用Linq:

var matchingvalues = myList
    .Where(stringToCheck => stringToCheck.Contains(myString));

如果您只想返回第一个匹配项:

var match = myList
    .FirstOrDefault(stringToCheck => stringToCheck.Contains(myString));

if(match != null)
    //Do stuff

+1-或用第二种情况替换WhereFirstOrDefaultmyList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))
Habib 2013年

好答案。但是,出于好奇,为什么要matching由编译器确定(var)?由于我知道我的列表是type Stringstring matching在这种情况下可以安全使用吗?
Dimitris Iliadis 2013年

1
@JimIliadis在这种情况下,“ var”和“ string”的含义完全相同-编译器非常聪明,可以知道结果只能是“ string”。var实际上只是一种编码风格的东西(当不使用匿名类型时)
Dave Bish 2013年

评论过旧的线程,但是发现了一个例外。当您使用firstordefault()时,请确保它也可以返回默认值。因此,假设您传递的是一个Empy字符串,即mystring =“”,并且您期望什么都不会显示,但是由于您选择了firstordefault,它仍将显示列表的第一项。
Dirty Developer

@DirtyDeveloper不确定您的意思是什么-如果目标列表中没有空字符串,则示例将返回'null。如果您尝试在结构类型上使用FirstOrDefault(),那么您是对的,例如List <int>-FirstOrDefault()将返回'0'而不是null-但是,问题是关于字符串的
Dave Bish

29

基本答案是:您需要遍历循环并检查任何包含指定字符串的元素。因此,假设代码是:

foreach(string item in myList)
{
    if(item.Contains(myString))
       return item;
}

等效但简洁的代码是:

mylist.Where(x => x.Contains(myString)).FirstOrDefault();

在此,x是一个类似于上述代码中“ item”的参数。


12
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}

9
for (int i = 0; i < myList.Length; i++)
{
    if (myList[i].Contains(myString)) // (you use the word "contains". either equals or indexof might be appropriate)
    {
        return i;
    }
}

旧时尚循环几乎总是最快的。


既然我追求效率,那么您是否建议该方法更快(因此更有效)?
Dimitris Iliadis 2013年

2
我还没有对它进行性能测试,但我想这会更快。只需要遍历该列表,直到找到某项内容并尽早爆发(如Linq选项可能写得好就可以了),没有linq的方法调用开销或linq的lambda开销。并不是那些令人担忧的巨大原因,而是会导致性能下降。
麦凯2013年

为什么不使用List.Equals()?
F8ER

@ V.7因为他只想知道列表中的一项是否包含子字符串。list.equals不是作业的正确工具[“ abc”,“ def”,“ ghi”]确实包含OP描述它的方式的“ hi”。list.equals甚至没有正确的数据类型。
麦凯

6

如果要包含字符串的字符串列表:

var newList = myList.Where(x => x.Contains(myString)).ToList();

另一种选择是使用Linq FirstOrDefault

var element = myList.Where(x => x.Contains(myString)).FirstOrDefault();

请记住,该Contains方法区分大小写。


1
关于区分大小写的好提醒,实现StringComparison.InvariantCultureIgnoreCase
JoshYates1980 '17

2

您可以使用Linq的FirstOrDefault扩展方法:

string element = myList.FirstOrDefault(s => s.Contains(myString));

这将返回包含子字符串的fist元素myString,或者null如果未找到此类元素。

如果您只需要索引,请使用List<T>该类的FindIndex方法:

int index = myList.FindIndex(s => s.Contains(myString));

这将返回包含子字符串的fist元素的索引myString,或者-1如果找不到此类元素,则返回该索引。


2

这里有很多好的答案,但是我使用一个简单的使用Exists的答案,如下所示:

foreach (var setting in FullList)
{
    if(cleanList.Exists(x => x.ProcedureName == setting.ProcedureName)) 
       setting.IsActive = true; // do you business logic here 
    else
       setting.IsActive = false;
    updateList.Add(setting);
}

2

您应该可以使用这样的东西,它对我来说还可以:

var valuesToMatch = yourList.Where(stringCheck => stringCheck.Contains(myString));

或类似的东西,如果您需要查看不匹配的地方。

 var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));

1

您可以使用

var match=myList.Where(item=>item.Contains("Required String"));
foreach(var i in match)
{
//do something with the matched items
}

LINQ为您提供了“查询”任何数据收集的功能。您可以对集合(这里是字符串的集合(列表))使用类似数据库查询(选择,位置等)的语法。

所以您的操作就像“从满足条件的列表中获取物品”

在您正在使用“ lambda表达式”的位置

简单地说一下lambda表达式就像(输入参数=>返回值)

因此对于参数“ item”,它返回“ item.Contains(” required string“)”。因此,如果该项目包含字符串,则返回true,因为它满足条件,因此可以从列表中选择它。


1

为简单起见,请使用此代码;

foreach(string item in myList)//Iterate through each item.
{
 if(item.Contains("Search Term")//True if the item contains search pattern.
 {
   return item;//Return the matched item.
 }
}

或者,使用for循环执行此操作;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }

只是指出一点,您错过了其中一行代码的结尾括号。.if(item.Contains(“ Search Term”))
Alex

0

我在其他答案中没有看到bool选项,因此希望下面的代码能对某人有所帮助。

只需使用 Any()

string myString = "test";
bool exists = myList
             .Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();

0

可以组合Any,Where,First和FirstOrDefault;或者只是根据需要将谓词放入任何一种方法中。

除非希望在找不到匹配项时引发异常,否则您应该避免使用First。通常,FirstOrDefault是更好的选择,只要您知道如果找不到匹配项,则它将返回类型的默认值(字符串的默认值为null,int为0,bool为false等)。

using System.Collections.Generic;
using System.Linq;


bool exists;
string firstMatch;
IEnumerable<string> matchingList;

var myList = new List<string>() { "foo", "bar", "foobar" };

exists = myList.Any(x => x.Contains("o"));
// exists => true

firstMatch = myList.FirstOrDefault(x => x.Contains("o"));
firstMatch = myList.First(x => x.Contains("o"));
// firstMatch => "foo"

firstMatch = myList.First(x => x.Contains("dark side"));
// throws exception because no element contains "dark side"

firstMatch = myList.FirstOrDefault(x => x.Contains("dark side"));
// firstMatch => null

matchingList = myList.Where(x => x.Contains("o")); 
// matchingList => { "foo", "foobar" }

测试此代码@ https://rextester.com/TXDL57489

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.