Linq Matching Pattern - c#

I have to search a list of strings in CityList and if it contains all search strings
then it should return true otherwise false.
When i search "London","Dallas" against CityList it should return false,because
"Dallas" is missing in CityList.
var CityList=new string[] { "London","Paris","Houston","Mexico","Budapest"}
var search =new string[] {"London","Dallas"};
How to rewrite the following ?
var result = CityList.Select(c => c).ToList().FindAll(search.ToArray());

Try the following:
var hasAll = !search.Except(CityList).Any();
By the way, you should never write something.Select(c => c); such a statement will do nothing but make the program a tiny bit slower.

Try this:
var result = search.All(s => CityList.Contains(s));

You have various possibilities:
var result = CityList.Union(search).Count() == CityList.Count();
var result2 = search.All(s => CityList.Contains(s));
var result3 = search.ToList().TrueForAll(s => CityList.Contains(s));
var result4 = CityList.Intersect(search).Count() == search.Count();

That quite an easy one
search.All(c => CityList.Contains(c))
All will only satify when all predicates return true, then we check if the citylist contains the item

Related

Get return value from function call within lambda expression

Consider the following C# line:
var item = listOfItems.FirstOrDefault(i => GetResult(i) <= upperLimit);
My question is, is there a way of getting the return value of GetResult(i) from within that line?
The obvious answer is have two lines:
var item = listOfItems.FirstOrDefault(i => GetResult(i) <= upperLimit);
var result = GetResult(item);
But it seems a bit inefficient to call the same function twice... Is a way have the result with just one call?
You can use this (assuming GetResult returns an int):
int? result = null;
var item = listOfItems.FirstOrDefault(x => (result = GetResult(x)) <= upperLimit);
This solution will keep the lazyness of FirstOrDefault : it will stop at first match found.
You can select both the item and the result of invoking GetResult on the item in an anonymous type to get them both like this:
var itemAndResult = listOfItems
.Select(x => new {Item = x, Result = GetResult(x)})
.Where(a => a.Result <= upperLimit)
.FirstOrDefault();
var item = itemAndResult.Item;
var result = itemAndResult.Result;

How to prevent a System.IndexOutOfRangeException in a LINQ WHERE?

I'm facing this exception when I'm using String.Split with random strings.
List<string> linhas = new List<string>();
linhas.Add("123;abc");
linhas.Add("456;def");
linhas.Add("789;ghi");
linhas.Add("chocolate");
var novas = linhas.Where(l => l.ToString().Split(';')[1]=="def");
The last string "chocolate"doesn't contain a ";", so String.Split returns an array with a single string "chocolate". That's why you get the exception if you try to accesss the second.
You could use ElementAtOrDefault which returns null for strings instead:
var novas = linhas.Where(l => l.Split(';').ElementAtOrDefault(1) == "def");
A longer approach using an anonymous type:
var novas = linhas
.Select(l => new { Line = l, Split = l.Split(';') })
.Where(x => x.Split.Length >= 2 && x.Split[1] == "def")
.Select(x => x.Line);
I'm going to expand a little on Tim's answer and show a way to do a few extra things within your LINQ queries.
You can expand the logic within you Where clause to do some additional processes, which can make your code a bit more readable. This would be good for something small:
var novas = linhas.Where(l =>
{
var parts = l.Split(':');
return parts.Length > 1 ? parts[1] == "def" : false;
});
If you need multiple statements, you can wrap the body of your clause within curly braces, but then you need the return keyword.
Alternatively, if you have a lot of information that would make something inline like that unreadable, you can also use a separate method within your query.
public void FindTheStringImLookingFor()
{
var linhas = new List<string>();
linhas.Add("123;abc");
linhas.Add("456;def");
linhas.Add("789;ghi");
linhas.Add("chocolate");
var words = linhas.Where(GetTheStringIWant);
}
private bool GetTheStringIWant(string s)
{
var parts = s.Split(':');
// Do a lot of other operations that take a few lines.
return parts.Length > 1 ? parts[1] == "def" : false;
}

How to split this string to obtain just the name value

Hi I am looking for a simple way to et just the name after the CN value
CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net
is there an easy way to do this? I am currently doing this:
ResultPropertyValueCollection manager = result.Properties["manager"];
string managerUserName = manager[0].ToString();
string[] managerNameParts = managerUserName.Split(',');
string managerName = managerNameParts[0].Substring(4);
Console.WriteLine("Manager Name:" + managerName);
but it feels kind of bad.
This is a great place to use Regular Expressions. Try this:
var text = "CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net";
var match = Regex.Match(text, #"CN=([^,]+)");
if (match.Success) return match.Groups[0].Value;
The expression CN=([^,]+) will look for the text CN= followed by one or more non-commas, and will stick that part of it into Groups[0].
You can do this:
var name = "CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net"
.Split(',')[0].Split('=')[1];
Demo
What it does is splits on , and takes the first element and then splits it by = and takes the second element.
If you cannot have the same format, you can do a regex:
Regex.Match(name,#"(?<=CN=)[^,]+").Value;
Another option, using LINQ.
If the name/value pair exists anywhere in the string, you'll get it; if not, managerName will be null.
var managerName = input.Split(',')
.Where(x => x.StartsWith("CN="))
.Select(x => x.Split('=')[1])
.SingleOrDefault();
I find doing it like this fairly easy to read:
var input = #"CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net";
var items = input.Split(',');
var keyValues = items.Select(x =>
{
var split = x.Split('=');
return new { Key = split[0], Value = split[1] };
});
var managerName = keyValues.Single(x => x.Key == "CN").Value;

How to use Linq to check if a list of strings contains any string in a list

I'm constructing a linq query that will check is a string in the DB contains any of the strings in a list of strings.
Something like.
query = query.Where(x => x.tags
.Contains(--any of the items in my list of strings--));
I'd also like to know how many of the items in the list were matched.
Any help would be appreciated.
Update: I should have mentioned that tags is a string not a list. And I am adding on a couple more wheres that are not related to tags before the query actually runs. This is running against entity framework.
EDIT: This answer assumed that tags was a collection of strings...
It sounds like you might want:
var list = new List<string> { ... };
var query = query.Where(x => x.tags.Any(tag => list.Contains(tag));
Or:
var list = new List<string> { ... };
var query = query.Where(x => x.tags.Intersect(list).Any());
(If this is using LINQ to SQL or EF, you may find one works but the other doesn't. In just LINQ to Objects, both should work.)
To get the count, you'd need something like:
var result = query.Select(x => new { x, count = x.tags.Count(tag => list.Contains(tag)) })
.Where(pair => pair.count != 0);
Then each element of result is a pair of x (the item) and count (the number of matching tags).
I've done something like this before:
var myList = new List<string>();
myList.Add("One");
myList.Add("Two");
var matches = query.Where(x => myList.Any(y => x.tags.Contains(y)));
like this:
List<string> list = new List<string>();
list.Add("One");
list.Add("Two");
var result = query.Where(x => list.Contains(x.tags));
I am not quite sure from your question if x.tags is a string or list, if it is a list Jon Skeet's answer is correct. If I understand you correctly though x.tags is a string of strings. If so then the solution is:
list.Any(x => x.tags.IndexOf(x) > -1)
to count them do
list.Count(x => x.tags.IndexOf(x) > -1)
var t = new List<string> { "a", "b", "c" };
var y = "a b d";
var res = y.Count(x => t.Contains(x.ToString()));
I faced a similar problem recently and here's how I managed to work it out:
var list = [list of strings];
if (list != null && list.Any())
{
queryable = queryable.Where(x => x.tags != null);
var tagQueries = new List<IQueryable<WhateverTheDbModelIs>>();
foreach (var element in list)
{
tagQueries.Add(queryable.Where(x => x.tags.Contains(element)));
}
IQueryable<WhateverTheDbModelIs> query = tagQueries.FirstOrDefault();
foreach (var tagQuery in tagQueries)
{
query = query.Union(tagQuery);
}
queryable = queryable.Intersect(query);
}
probably not the best option but something a less experienced developer can understand and use

Check if the Array has something like my Text

I have a array of strings . I need to check in the array if it has something like "abcd". How to achive this in C#. I tried using the
var pathBits = new[] {"abcde ","abcd &"};
var item ="abcd";
var results = Array.FindAll(pathBits, s => s.Equals(item ));
maybe something like this:
var result = pathBits.Any(y => y.Contains(item));
That will give you true if the array contains an item that has a value like item. If you want to select all those values you should use:
var result = pathBits.Where(y => y.Contains(item));
which will give you an IEnumerable of the items from the list that contain the value item.
When you say 'something like "abcd"' do you mean "Starts with" or "Contains"?
The current code will only find strings in pathBits which are exactly equal to item ("abcd" ?)
The general shape is fine but to find non-exact matches you need to change the predicate
e.g.
string[] src = new[] { "abcde", "abcd &" };
var results = Array.FindAll<string>(src, name => name.Contains("abcd"));
This can also be implemented using the Linq IEnumerable<> extensions
e.g.
string[] src = new[] { "abcde", "abcd &" };
var results = src.Where(name => name.Contains("abcd"));
hth,
Alan.
This might be of some use
string[] pathBits = { "abcde ", "abcd &" };
var item = "abcd";
if (pathBits.Contains(item)) ;
{
}
You cannot use
var pathbits = { "abcde ", "abcd &" };
Please let me know if you have any problem
Is this what your looking for?
string[] pathBits = { "abcde ", "abcd &", "222" };
var item = "abcd";
var results = Array.FindAll<string>(pathBits, s => s.Contains(item));
results will have 2 items.
I'm not sure exactly what you want, but this would get all array allements that contain the string "abcd" -
String[] pathBits = {"abcde ","abcd &"};
var item ="abcd";
var results = pathBits.Where(s => s.IndexOf("abcd") > -1);

Categories

Resources