Find substring in a list of strings - c#

I have a list like so and I want to be able to search within this list for a substring coming from another string. Example:
List<string> list = new List<string>();
string srch = "There";
list.Add("1234 - Hello");
list.Add("4234 - There");
list.Add("2342 - World");
I want to search for "There" within my list and return "4234 - There". I've tried:
var mySearch = list.FindAll(S => s.substring(srch));
foreach(var temp in mySearch)
{
string result = temp;
}

With Linq, just retrieving the first result:
string result = list.FirstOrDefault(s => s.Contains(srch));
To do this w/o Linq (e.g. for earlier .NET version such as .NET 2.0) you can use List<T>'s FindAll method, which in this case would return all items in the list that contain the search term:
var resultList = list.FindAll(delegate(string s) { return s.Contains(srch); });

To return all th entries:
IEnumerable<string> result = list.Where(s => s.Contains(search));
Only the first one:
string result = list.FirstOrDefault(s => s.Contains(search));

What you've written causes the compile error
The best overloaded method match for 'string.Substring(int)' has some invalid arguments
Substring is used to get part of string using character position and/or length of the resultant string.
for example
srch.Substring(1, 3) returns the string "her"
As other have mentioned you should use Contains which tells you if one string occurs within another. If you wanted to know the actual position you'd use IndexOf

same problem i had to do.
You need this:
myList.Where(listStrinEntry => myString.IndexOf(listStringEntry) != -1)
Where:
myList is List<String> has the values
that myString has to contain at any position
So de facto you search if myString contains any of the entries from the list.
Hope this is what you wanted...

i like to use indexOf or contains
someString.IndexOf("this");
someString.Contains("this");

And for CaseSensitive use:
YourObj yourobj = list.FirstOrDefault(obj => obj.SomeString.ToLower().Contains("some substring"));
OR
YourObj yourobj = list.FirstOrDefault(obj => obj.SomeString.ToUpper().Contains("some substring"));

Related

Unity Lists Finding 2 letters in a list containing 5 letter words [duplicate]

I have a list like so and I want to be able to search within this list for a substring coming from another string. Example:
List<string> list = new List<string>();
string srch = "There";
list.Add("1234 - Hello");
list.Add("4234 - There");
list.Add("2342 - World");
I want to search for "There" within my list and return "4234 - There". I've tried:
var mySearch = list.FindAll(S => s.substring(srch));
foreach(var temp in mySearch)
{
string result = temp;
}
With Linq, just retrieving the first result:
string result = list.FirstOrDefault(s => s.Contains(srch));
To do this w/o Linq (e.g. for earlier .NET version such as .NET 2.0) you can use List<T>'s FindAll method, which in this case would return all items in the list that contain the search term:
var resultList = list.FindAll(delegate(string s) { return s.Contains(srch); });
To return all th entries:
IEnumerable<string> result = list.Where(s => s.Contains(search));
Only the first one:
string result = list.FirstOrDefault(s => s.Contains(search));
What you've written causes the compile error
The best overloaded method match for 'string.Substring(int)' has some invalid arguments
Substring is used to get part of string using character position and/or length of the resultant string.
for example
srch.Substring(1, 3) returns the string "her"
As other have mentioned you should use Contains which tells you if one string occurs within another. If you wanted to know the actual position you'd use IndexOf
same problem i had to do.
You need this:
myList.Where(listStrinEntry => myString.IndexOf(listStringEntry) != -1)
Where:
myList is List<String> has the values
that myString has to contain at any position
So de facto you search if myString contains any of the entries from the list.
Hope this is what you wanted...
i like to use indexOf or contains
someString.IndexOf("this");
someString.Contains("this");
And for CaseSensitive use:
YourObj yourobj = list.FirstOrDefault(obj => obj.SomeString.ToLower().Contains("some substring"));
OR
YourObj yourobj = list.FirstOrDefault(obj => obj.SomeString.ToUpper().Contains("some substring"));

Check string if it contain any of string array value, then get the substring

This may be a sub-question to this SO Question. I want to check the string against an array of string or list.
Example
string address = "1st nice ave 1st floor";
//For now, I'm getting the list from a text file but could move to use an EF
List<string> streetType = File.ReadLines(AppDomain.CurrentDomain.BaseDirectory + #"streetType.csv")
.Where(x => x.Length > 0)
.Select(y => y.ToLowerInvariant())
.ToArray();
the purpose is to strip the extra address details after the avenue, the csv file contains all USPS accepted street type.
This is what I have now
//this only returns boolean value, I got this from the SO above
streetType.Any(testaddress.ToLower().Contains);
//I also have this
Array.Exists<string>(streetType, (Predicate<string>)delegate (string s)
{
return testaddress.IndexOf(s, StringComparison.OrdinalIgnoreCase) > -1;
});
I've been looking for hours how to resolve this then I came across the SO question which is exactly what I also want but I need to get the substring to for stripping.
If there's a linq query, that would be awesome. The only way I can think of doing this is with foreach and inner if.
Example of the array values
ave
avenue
pkwy
Update:
Here is my answer, I forgot to mention that the array lookup needs to match the exact string from the address string. I ended up using regex. This is the expanded/modified answer of #giladGreen.
var result = from item in streetTypes
let index = Regex.Match(address.ToLowerInvariant(), #"\b" + item.ToLowerInvariant() + #"\b")
where index.Success == true
select address.ToLowerInvariant().Substring(0, index.Index + item.Length);
Can somebody convert this to lambda expression? I tried I failed.
Thank you all
Use IndexOf to understand of item is present in address and if so to return the string after it:
var result = from item in streetType
let index = address.IndexOf(item)
where index != -1
select address.SubString(0, index);
One way to do this would be to simply Split each address on the streetType list, and then take the first item (at index[0]) from the resulting array:
addresses = addresses
.Select(address => address.Split(streetTypes.ToArray(), StringSplitOptions.None)[0])
.ToList();
I might be inclined to do something like this:
string[] markers = "ave avenue pkwy".Split();
string address = "1st nice ave 1st floor";
var result = markers
.Select((marker, index) => new
{
markerIndex = index,
addressPosition = address.IndexOf(marker)
})
.FirstOrDefault(x => x.addressPosition != -1);
// returns { markerIndex = 0, addressPosition = 9 }
Then result is an object that is either null (if the marker is not found) or is an object containing both markerIndex, which tells you which marker was found first, and addressPosition which tells you the character at which the marker string was found.

Check if a particular string is contained in a list of strings

I'm trying to search a string to see if it contains any strings from a list,
var s = driver.FindElement(By.Id("list"));
var innerHtml = s.GetAttribute("innerHTML");
innerHtml is the string I want to search for a list of strings provided by me, example
var list = new List<string> { "One", "Two", "Three" };
so if say innerHtml contains "One" output Match: One
You can do this in the following way:
int result = list.IndexOf(innerHTML);
It will return the index of the item with which there is a match, else if not found it would return -1.
If you want a string output, as mentioned in the question, you may do something like:
if (result != -1)
Console.WriteLine(list[result] + " matched.");
else
Console.WriteLine("No match found");
Another simple way to do this is:
string matchedElement = list.Find(x => x.Equals(innerHTML));
This would return the matched element if there is a match, otherwise it would return a null.
See docs for more details.
You can do it with LINQ by applying Contains to innerHtml for each of the items on the list:
var matches = list.Where(item => innerHtml.Contains(item)).ToList();
Variable matches would contain a subset of strings from the list which are matched inside innerHtml.
Note: This approach does not match at word boundaries, which means that you would find a match of "One" when innerHtml contains "Onerous".
foreach(var str in list)
{
if (innerHtml.Contains(str))
{
// match found, do your stuff.
}
}
String.Contains documentation
For those who want to serach Arrray of chars in another list of strings
List WildCard = new() { "", "%", "?" };
List PlateNo = new() { "13eer", "rt4444", "45566" };
if (WildCard.Any(x => PlateNo.Any(y => y.Contains(x))))
Console.WriteLine("Plate has wildchar}");

Transforming List<string> into a tokenised string

I have a list of strings in a List container class that look like the following:
MainMenuItem|MenuItem|subItemX
..
..
..
..
MainMenuItem|MenuItem|subItem99
What I am trying to do is transform the string, using LINQ, so that the first item for each of the tokenised string is removed.
This is the code I already have:
protected static List<string> _menuItems = GetMenuItemsFromXMLFile();
_menuItems.Where(x => x.Contains(menuItemToSearch)).ToList();
First line of code is returning an entire XML file with all the menu items that exist within an application in a tokenised form;
The second line is saying 'get me all menu items that belong to menuItemToSearch'.
menuItemToSearch is contained in the delimited string that is returned. How do I remove it using linq?
EXAMPLE
Before transform: MainMenuItem|MenuItem|subItem99
After transform : MenuItem|subItem99
Hope the example illustrates my intentions
Thanks
You can take a substring from the first position of the pipe symbol '|' to remove the first item from a string, like this:
var str = "MainMenuItem|MenuItem|subItemX";
var dropFirst = str.Substring(str.IndexOf('|')+1);
Demo.
Apply this to all strings from the list in a LINQ Select to produce the desired result:
var res = _menuItems
.Where(x => x.Contains(menuItemToSearch))
.Select(str => str.Substring(str.IndexOf('|')+1))
.ToList();
Maybe sth like this can help you.
var regex = new Regex("[^\\|]+\\|(.+)");
var list = new List<string>(new string[] { "MainMenuItem|MenuItem|subItem99", "MainMenuItem|MenuItem|subItem99" });
var result = list.Where(p => regex.IsMatch(p)).Select(p => regex.Match(p).Groups[1]).ToList();
This should work correctly.

How can I trim all elements in a list?

I'm trying the following
string tl = " aaa, bbb, ccc, dddd eeeee";
var tags = new List<string>();
tags.AddRange(tl.Split(','));
tags.ForEach(x => x = x.Trim().TrimStart().TrimEnd());
var result = String.Join(",", tags.ToArray());
But it doesn't work, the tags always come back as " aaa", " bbb".
How can I trim all elements in a list?
// you can omit the final ToArray call if you're using .NET 4
var result = string.Join(",", tl.Split(',').Select(s => s.Trim()).ToArray());
If you only need the final result string, rather than the intermediate collection, then you could use a regular expression to tidy the string. You'll need to benchmark to determine whether or not the regex outperforms the split-trim-join technique:
var result = Regex.Replace(tl, #"(?<=^|,) +| +(?=,|$)", "");
Ran into the same problem. #Lee already explained that Lamda .ForEach() uses a copy.
You can write an Extension Method like this and use a for loop (foreach also not possible):
public static class StringListExtensions
{
public static void TrimAll(this List<string> stringList)
{
for (int i = 0; i < stringList.Count; i++)
{
stringList[i] = stringList[i].Trim(); //warning: do not change this to lambda expression (.ForEach() uses a copy)
}
}
}
Use it like this:
var productNumbers = new List<string>(){ "11111", " 22222 " }
productNumbers.TrimAll();
should result in: List(){ "11111", "22222" }
I didn't use the split and re-join solution (chosen solution) because there can be a comma inside one of the string items. The regex version is not self explanatory. This is old-school but safer and can be easily understood...
The reason your approach doesn't work is that the x is a copy of the current string reference being processed in the ForEach call (i.e. local to the delegate). Therefore the assignment doesn't affect the item referenced in the list.
Try
List<string> lstSelect = string_test.Split(',').Select(x => x.Trim()).ToList();
What's going on is that you're trying to modify a collection using a foreach statement- which is a no-no. Collections cannot be modified with a foreach.
You'll need to modifiy it a for loop, or, using lambdas, you can use LukeH's solution.
Your problem is that there is no comma between dddd and eeeee. If you want those to be separate, you need to split on ' ', strip the commas, and then trim extra whitespace.
string tl = " aaa, bbb, ccc, dddd eeeee";
var result = t1.Split(' ').Where(s => !String.IsNullOrEmpty())
.Select(s => s.Replace(',','').Trim())
.ToArray();
This can be easily done through LINQ one liner:
Just remember rule of Thumb :
SELECT -> For transforming the elements
WHERE -> For Filtering the elements
Now, we can use the SELECT clause to Transform all the elements:
List<string> listString = new List<string>(){"abc ", "xyz ", " Abc ", " zx"};
listString = listString.Select(x => x.Trim()).ToList();
Thats all and things are done.

Categories