Check if list contains element that contains a string and get that element
Asked Answered
L

13

201

While searching for an answer to this question, I've run into similar ones utilizing LINQ but I haven't been able to fully understand them (and thus, implement them), as I'm not familiarized with it. What I would like to, basically, is this:

  1. Check if any element of a list contains a specific string.
  2. If it does, get that element.

I honestly don't know how I would go about doing that. What I can come up with is this (not working, of course):

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

I know WHY it does not work:

  • myList.Contains() does not return true, since it will check for if a whole element of the list matches the string I specified.
  • myList.IndexOf() will not find an occurrence, since, as it is the case again, it will check for an element matching the string.

Still, I have no clue how to solve this problem, but I figure I'll have to use LINQ as suggested in similar questions to mine. That being said, if that's the case here, I'd like for the answerer to explain to me the use of LINQ in their example (as I said, I haven't bothered with it in my time with C#). Thank you in advance guys (and gals?).

EDIT: I have come up with a solution; just loop through the list, check if current element contains the string and then set a string equal to the current element. I'm wondering, though, is there a more efficient way than this?

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

for (int i = 0; i < myList.Count; i++)
{
    if (myList[i].Contains(myString))
        element = myList[i];
}
Lanita answered 12/9, 2013 at 14:39 Comment(2)
as I mention in my answer, old fashion loops (like you have as your question) are almost always fastest. But you could perf test it if you care enough.Ruskin
There could be multiple strings in your list containing your string myString, in your current loop, you will get the last element. It depends on you if you want to find the first or last, if you just want to find the first, then break the loop after finding the item.Anurag
T
267

You should be able to use Linq here:

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

If you simply wish to return the first matching item:

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

if(match != null)
    //Do stuff
Tax answered 12/9, 2013 at 14:44 Comment(6)
+1 - Or replace Where with FirstOrDefault in your second case myList.FirstOrDefault(stringToCheck => stringToCheck.Contains(myString))Anurag
Great answer. Just out of curiosity, though: why is it that matching is compiler-determined (var)? Since I know that my list is of type String, would it be safe to use string matching in this case?Lanita
@JimIliadis "var" and "string" mean exactly the same thing in this case - the compiler is smart enough to know that the result can only be 'string'. var is really just a coding style thing (when not using anonymous types)Tax
commenting on too old thread, but found one exception on this. when you use firstordefault() make sure it can return default value as well. so, let's suppose your are passing an empy string i.e. mystring ="" and you are expecting nothing to show, but still it will display the first item of the list because you have selected firstordefault.Mortician
@DirtyDeveloper Not sure what you mean by this - your example would return 'null, if there were no empty strings in target list. You're right if you're attempting to use FirstOrDefault() on a struct type, e.g. List<int> - FirstOrDefault() will return '0' and not null - however, the question was specifically about stringsTax
"Any" Will work better var matchingvalues = myList .Any(stringToCheck => stringToCheck.Contains(myString));Duplicate
R
42

The basic answer is: you need to iterate through loop and check any element contains the specified string. So, let's say the code is:

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

The equivalent, but terse, code is:

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

Here, x is a parameter that acts like item in the above code.

Relation answered 12/9, 2013 at 14:46 Comment(2)
how is this written in vb mylist.Where(x => x.Contains(myString)).FirstOrDefault();Nellynelms
To avoid to check all elements, even if the first is a good result, I think that this might be faster: var element = myList.FirstOrDefault(x => x.Contains(myString));Iceni
I
15
string result = myList.FirstOrDefault(x => x == myString)
if(result != null)
{
  //found
}
Injurious answered 12/9, 2013 at 14:43 Comment(0)
R
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;
    }
}

Old fashion loops are almost always the fastest.

Ruskin answered 12/9, 2013 at 14:44 Comment(4)
Since I go for efficiency, are you suggesting that this method is faster (thus, more efficient)?Lanita
I haven't perf tested it, but I'd guess that this would be faster. Only ever requires one pass through the list, until it finds something and breaks out early (like the Linq options might do if written well), doesn't have the method invocation overhead of linq, or the lambda overhead of linq either. Not that those are huge causes of concern, but can cause some performance hit.Ruskin
Why do not use List.Equals()?Raleighraley
@V.7 Because he only wants to know if one item in the list contains a substring. list.equals is not the correct tool for the job [ "abc", "def", "ghi" ] does contain "hi" the way the OP describes it. list.equals doesn't even take the correct datatypes.Ruskin
A
7

If you want a list of strings containing your string:

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

Another option is to use Linq FirstOrDefault

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

Keep in mind that Contains method is case sensitive.

Alfano answered 12/9, 2013 at 14:44 Comment(1)
Good reminder about case sensitive, implement StringComparison.InvariantCultureIgnoreCaseHeelandtoe
A
3

You could use Linq's FirstOrDefault extension method:

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

This will return the fist element that contains the substring myString, or null if no such element is found.

If all you need is the index, use the List<T> class's FindIndex method:

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

This will return the the index of fist element that contains the substring myString, or -1 if no such element is found.

Anecdotage answered 12/9, 2013 at 14:44 Comment(0)
W
3

Many good answers here, but I use a simple one using Exists, as below:

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);
}
Wallpaper answered 3/2, 2018 at 13:30 Comment(0)
T
2

You should be able to use something like this, it has worked okay for me:

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

or something like this, if you need to look where it doesn't match.

 var valuesToMatch = yourList.Where(stringCheck => !stringCheck.Contains(myString));
Toaster answered 9/8, 2019 at 14:10 Comment(0)
U
1

To keep it simple use this;

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.
 }
}

Alternatively,to do this with for loop,use this;

    for (int iterator = 0; iterator < myList.Count; iterator++)
    {
        if (myList[iterator].Contains("String Pattern"))
        {
            return myList[iterator];
        }
    }
Underplay answered 12/9, 2013 at 14:50 Comment(1)
Just to point out, you missed an end bracket off one of the lines of code.. if( item.Contains("Search Term") )Sheathbill
S
1

you can use

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

LINQ provides you with capabilities to "query" any collection of data. You can use syntax like a database query (select, where, etc) on a collection (here the collection (list) of strings).

so you are doing like "get me items from the list Where it satisfies a given condition"

inside the Where you are using a "lambda expression"

to tell briefly lambda expression is something like (input parameter => return value)

so for a parameter "item", it returns "item.Contains("required string")" . So it returns true if the item contains the string and thereby it gets selected from the list since it satisfied the condition.

Stenopetalous answered 12/9, 2013 at 14:56 Comment(0)
T
1

It is possible to combine Any, Where, First and FirstOrDefault; or just place the predicate in any of those methods depending on what is needed.

You should probably avoid using First unless you want to have an exception thrown when no match is found. FirstOrDefault is usually the better option as long as you know it will return the type's default if no match is found (string's default is null, int is 0, bool is false, etc).

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" }

Test this code @ https://rextester.com/TXDL57489

Transsonic answered 13/7, 2020 at 17:41 Comment(0)
W
0

I have not seen bool option in other answers so I hope below code will help someone.

Just use Any()

string myString = "test";
bool exists = myList
             .Where(w => w.COLUMN_TO_CHECK.Contains(myString)).Any();
Whatley answered 1/3, 2019 at 10:34 Comment(0)
H
-2

You can check the list is empty or not in multiple ways.

1)Check list is null and then check count is greater than zero like below:-

if(myList!=null && myList.Count>0)
{
    //List has more than one record.
}

2)Check list null and count greater than zero using linq query like below:-

if(myList!=null && myList.Count>0)
{
    //List has more than one record.
}
Hensel answered 22/7, 2021 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.